Transponer lista de listas sin un bucle forMe gustaría tener un método para transponer una lista de listas sin usar un bucle for. Es decir, alguna función (llámela "Listtranspose", por ejemplo) que voltea las "filas" y las "columnas" de una lista de listas, así:
listlist = {{"cat", "dog", "mouse"}, {"meow", "bark", "squeak"}};
tranlist = Listtranspose(listlist);
Show(tranlist);
/*Result:
{{"cat", "meow"}, {"dog", "bark"}, {"mouse", "squeak}}
Una implementación alternativa podría ser algo como:
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});
Me gusta más la última implementación, ya que es posible que solo necesite transponer solo un subconjunto de "columnas", no la lista completa.
Por supuesto, esto se puede hacer usando un For Loop, pero la razón para solicitarlo es que For Loops puede ser lento. Trabajo con grandes bloques de texto y creo que esto me ayudaría a acelerar mucho las cosas.
Crédito a @vince_faller por preguntar esto originalmente.Transponer lista de listas sin un bucle for
secuencias de comandosRe: Transponer lista de listas sin bucle forPensando en esto un poco más.Todavía no puedo superar el ciclo for, pero pensé que escribiría esto en caso de que ayude a alguien.
// make a blank data table with the right shape
dt = As Table(J(nr, nc, .), <<PRIVATE></PRIVATE>
Re: Transponer lista de listas sin bucle for@Craige_Hales Gracias por la tremenda perspicacia Craig. Estoy de acuerdo, hice una prueba de velocidad del método de asignación en paralelo frente al bucle for, y la asignación en paralelo fue mucho más lenta. Mi matriz de lista era 718r x 14182c, por lo que> 10 millones de elementos. Ejecuté el script durante ~10 minutos y la operación no se completó. Esto parece ser un poco más lento de lo que predicen los datos anteriores, pero hay demasiadas variables para considerar (por ejemplo, sistema informático, proporción de columnas a filas). For loop es mucho más rápido a ~ 10.1 s para la misma tabla.
Sin embargo, aún más lento de lo que me gustaría. Sería genial tener una función JMP que pueda hacer esto internamente.
Re: Transponer lista de listas sin bucle forPero, después de algunas pruebas, creo que un bucle anidado simple será más rápido que cualquier otro enfoque basado en 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 - ¡Desafío!
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.El bucle for de línea azul es consistentemente mejor. La tabla JSON púrpura podría superarlo, pero me estoy quedando sin memoria. El truco de la asignación paralela comienza a fallar para números grandes.
La asignación paralela probablemente esté bloqueando subprocesos entre sí, todo el tiempo. Al principio supera a la tabla de datos json debido a los diferentes gastos generales entre los dos.
Re: Transponer lista de listas sin bucle forSí, sería bueno tener más funciones de manipulación de listas. No se me ocurre una forma agradable o rápida, pero después de jugar un poco se me ocurrió esto. Necesita JMP 15, falla 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 );lista = {{"león", "tigre", "puma"}, {"lámpara", "antorcha", "faros"}, {"alondra", "tucán", "paloma"}, {"césped", "terraza", "patio"}};
transpuesto = {{"león", "lámpara", "alondra", "césped"}, {"tigre", "antorcha", "tucán", "terraza"}, {"puma", " faros ", "paloma", "patio"}};
Muestre las tablas intermedias para ver lo que está haciendo. Una solución real debería tratar con filas de longitud desigual.
Re: Transponer lista de listas sin bucle for@Craige_Hales escribió una gran explicación que uso regularmente.Resolución de problemas de subprocesos múltiples mediante la asignación paralela
Re: Transponer lista de listas sin bucle for@vince_faller
Mente == Soplado.
Nunca he oído hablar de la función de asignación paralela antes. Intenté esto, y sí, funciona. Aunque estoy trabajando con cadenas de caracteres y esto es técnicamente una función de matriz, de alguna manera no le importa. Será interesante jugar con esto y ver si es más rápido que un bucle for. Intentaré actualizar aquí una vez que lo sepa.
¡Gracias por la idea!
Re: Transponer lista de listas sin bucle forJuro de arriba a abajo que vi a alguien hacer algo en la línea de
{"cat", "dog", "mouse", "meow", "bark", "squeak"}[[1 1, 1 1]]
// and had it return
{{"cat", "cat"}, {"cat", "cat"}}
durante una charla en el descubrimiento, pero nunca he podido recrearlo.¿Pudo haber sido todo un sueño?
Si no recuerdo mal, de alguna manera formaron una nueva lista a partir de una lista plana en una línea como esa.Probablemente no recuerdo bien.
Dicho esto, probablemente puedas hacer asignaciones paralelas muy rápido
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);