Transposer la liste des listes sans boucle forJe voudrais avoir une méthode pour transposer une liste de listes sans utiliser de boucle for. C'est-à-dire une fonction (appelez-la "Listtranspose" par exemple) qui inverse les "lignes" et les "colonnes" d'une liste de listes, comme ceci :
listlist = {{"cat", "dog", "mouse"}, {"meow", "bark", "squeak"}};
tranlist = Listtranspose(listlist);
Show(tranlist);
/*Result:
{{"cat", "meow"}, {"dog", "bark"}, {"mouse", "squeak}}
Une implémentation alternative pourrait être quelque chose comme :
listlist = {{"cat", "dog", "mouse"}, {"meow", "bark", "squeak"}};
nr = NItems(listlist);
col1 = listlist[1::nr][1];
col2 = listlist[1::nr][2];
col3 = listlist[1::nr][3];
translist = EvalList({col1, col2, col3});
J'aime mieux cette dernière implémentation car je n'aurais peut-être besoin de transposer qu'un sous-ensemble de "colonnes", pas la liste entière.
Bien sûr, cela peut être fait en utilisant une boucle For, mais la raison de cette demande est que les boucles For peuvent être lentes. Je travaille avec de gros blocs de texte et je pense que cela aiderait à accélérer considérablement les choses pour moi.
Crédit à @vince_faller pour avoir demandé cela à l'origine.Transposer la liste des listes sans boucle for
ScriptRe : Transposer la liste des listes sans boucle forPenser à cela un peu plus.Je ne peux toujours pas battre la boucle for, mais j'ai pensé que j'écrirais ceci au cas où cela aiderait quelqu'un.
// make a blank data table with the right shape
dt = As Table(J(nr, nc, .), <<PRIVATE></PRIVATE>
Re : Transposer la liste des listes sans boucle for@Craige_Hales Merci pour l'incroyable perspicacité Craig. Je suis d'accord, j'ai fait un test de vitesse de la méthode for loop vs parallel-assign, et l'assignation parallèle était beaucoup plus lente. Mon tableau de liste était de 718r x 14182c, donc> 10 millions d'éléments. J'ai exécuté le script pendant environ 10 minutes et l'opération ne s'est pas terminée. Cela semble être un peu plus lent que ce que vos données ci-dessus prédisent, mais trop de variables à prendre en compte (par exemple, le système informatique, le rapport des colonnes aux lignes ?). La boucle For est beaucoup plus rapide à ~ 10,1 s pour la même table.
Toujours plus lent que je le voudrais cependant. Ce serait formidable d'avoir une fonction JMP qui peut le faire en interne.
Re : Transposer la liste des listes sans boucle forMais, après quelques tests, je pense qu'une simple boucle imbriquée sera plus rapide que toute autre approche basée sur JSL.
result = {};
for( c = 1, c <= nc, c += 1,
thisrow = {}; // build a row from a column
for( r = 1, r <= nr, r += 1,
thisrow[r] = testList[r][c];
);
result[c] = thisrow;
);@DonMcCormack - Défi!
The blue-line for-loop is consistently better. The purple JSON-table might overtake it, but I'm running out of memory. The parallel-assign trick begins to fail for large numbers.La boucle for de la ligne bleue est toujours meilleure. La table JSON violette pourrait la dépasser, mais je manque de mémoire. L'astuce d'assignation parallèle commence à échouer pour les grands nombres.
L'affectation parallèle bloque probablement les threads les uns contre les autres, tout le temps. Il bat la table de données json au début en raison des frais généraux différents entre les deux.
Re : Transposer la liste des listes sans boucle forOui, ce serait bien d'avoir plus de fonctions de manipulation de liste. Je ne peux pas trouver un moyen agréable ou rapide, mais après avoir joué un peu, j'ai trouvé cela. Il a besoin de JMP 15, échoue en 14.
list = {{"lion", "tiger", "puma"}, {"lamp", "torch", "pharos"}, {"lark", "toucan", "pigeon"}, {"lawn", "terrace", "patio"}};
jlist = As JSON Expr( list );
dt1 = JSON To Data Table( jlist, invisible(1) );
dt1 << New Column( "row", numeric, setvalues( 1 + Floor( (0 :: (N Rows( dt1 ) - 1)) / N Items( list[1] ) ) ) );
dt2 = dt1 << Split( Split By( :row ), Split( column(dt1,1) ), Sort by Column Property, invisible(1) );
Close( dt1, nosave );
transposed = dt2[0, 0];
Close( dt2, nosave );
Show( list, transposed );liste = {{"lion", "tigre", "puma"}, {"lampe", "torche", "phare"}, {"alouette", "toucan", "pigeon"}, {"pelouse", "terrasse", "patio"}} ;
transposé = {{"lion", "lampe", "alouette", "pelouse"}, {"tigre", "torche", "toucan", "terrasse"}, {"puma", " phare ", "pigeon", "terrasse"}} ;
Affichez les tables intermédiaires pour voir ce qu'il fait. Une vraie solution devrait traiter des lignes de longueur inégale.
Re : Transposer la liste des listes sans boucle for@Craige_Hales a écrit une excellente explication que j'utilise régulièrement.Dépannage du multithreading à l'aide de Parallel Assign
Re : Transposer la liste des listes sans boucle for@vince_faller
Esprit == soufflé.
Je n'avais jamais entendu parler de la fonction Parallel Assign auparavant. J'ai essayé ceci, et oui, ça marche. Même si je travaille avec des chaînes de caractères et qu'il s'agit techniquement d'une fonction matricielle, cela ne s'en soucie pas. Il sera intéressant de jouer avec cela et de voir si c'est plus rapide qu'une boucle for. Je vais essayer de mettre à jour ici une fois que je le saurai.
Merci pour l'idée !
Re : Transposer la liste des listes sans boucle forJe jure haut et bas que j'ai vu quelqu'un faire quelque chose dans le sens de
{"cat", "dog", "mouse", "meow", "bark", "squeak"}[[1 1, 1 1]]
// and had it return
{{"cat", "cat"}, {"cat", "cat"}}
lors d'une conférence à la découverte mais je n'ai jamais pu la recréer.Tout aurait pu n'être qu'un rêve ?
Si je me souviens bien, ils ont en quelque sorte façonné une nouvelle liste à partir d'une liste plate en une seule ligne comme ça.Je ne me souviens probablement pas bien.
Cela étant dit, vous pouvez probablement effectuer une affectation parallèle très rapidement
names default to here(1);
listlist = {{"cat", "dog", "mouse"}, {"meow", "bark", "squeak"}};
m = J(nc, nr, -1);
::trans_list = Aslist(m);
Parallel Assign({l = listlist},
m[a, b] = (
::trans_list[a][b] = l[b][a];
)
);
show(::trans_list);