2010-11-24 34 views
13

Tengo una lista bidimensional y una lista unidimensional. Me gustaría insertar la lista 1D en la lista 2D como una columna adicional. Por ejemplo:Anexando a las filas de una tabla

array = {{a,1,2},{b,2,3},{c,3,4}}; 
column = {x,y,z}; 

convierte

final = {{a,1,2,x},{b,2,3,y},{c,3,4,z}}; 

he hecho esto de manera poco elegante:

Table[Insert[array[[i]], column[[i]], 4], {i, Length[array]}]; 

Mi pregunta: ¿cuál es la forma correcta de hacer esto en Mathematica? No creo que necesite el bucle que estoy usando. Mi solución se siente fea

Respuesta

14

Por ejemplo:

[email protected][[email protected], column] 

También se puede hacer es una función de este modo:

subListAppend = [email protected][[email protected]#1, #2] &; 
subListAppend[array, column] 

que hace que sea más fácil si se tiene que utilizar con frecuencia. Y, por supuesto, si desea insertar en cualquier lugar que no sea el final, puede usar Insert[].

subListInsert = [email protected][[email protected]#1, #2, #3] &; 
subListInsert[array, column, 2] 
--> {{a, x, 1, 2}, {b, y, 2, 3}, {c, z, 3, 4}} 

EDIT: Ya ha comenzado la discusión obligatoria optimización de la velocidad, he aquí algunos resultados utilizando this y una matriz 10000x200:

[email protected]{{array, List /@ column}}:    0.020 s 
[email protected][[email protected], column]:   0.067 s 
MapThread[Append, {array, column}]:     0.083 s 
MapThread[Insert[#1, #2, 4] &, {array, column}]: 0.095 s 
Map[Flatten, Flatten[{array, column}, {2}]]:  0.26 s 
ConstantArray based solution:      0.29 s 
Partition[[email protected][{array, column}], 4]: 0.48 s 

Y el ganador es ArrayFlatten!

+1

bien, que resolvieron el problema, gracias! Ahora necesito separar eso para entender * por qué *, pero eso es para mí. –

+0

Ve un elemento a la vez (por ejemplo, mira qué hace Transpose @ array) y lo resolverás :-). – Timo

+0

Sí, eso ayudó. Es como origami. Sabía que estaba peleando contra Mathematica innecesariamente. Gracias de nuevo. –

5

Otra posibilidad es

result = ConstantArray[0, Dimensions[array] + {0, 1}]; 
result[[All, 1 ;; Last[Dimensions[array]]]] = array; 
result[[All, -1]] = column; 

que parece ser más rápido en mi equipo para grandes matrices numéricas, aunque requiere una variable adicional. Si está tratando con entradas con valores reales, querrá usar

result = ConstantArray[0.0, Dimensions[array] + {0, 1}]; 

para mantener las ganancias de velocidad.

También hay

MapThread[Append, {array, column}] 

que también es rápido (y elegante OMI) sino que desempaquetar el resultado. (Pero si tiene entradas simbólicas como en el ejemplo, que no es una preocupación.)

+0

Gracias Brett. Su uso MapThread es de hecho elegante. Me complace haber visto la respuesta Transpose primero porque tengo la sensación de que los conceptos que utiliza son más ampliamente aplicables, sin embargo, esto es muy, muy conciso. Mis matrices no son lo suficientemente grandes como para garantizar las líneas adicionales de código para el enfoque ConstantArray y contienen principalmente datos simbólicos de todos modos. Aún así, cuatro enfoques completamente diferentes para el mismo problema: ¡eso es Mathematica! –

+0

Interesante, obtengo aproximadamente un 35% mejor 'Timing' usando el ejemplo de OP y un factor de diez mejor velocidad para matrices grandes (1k - 1M entradas) usando mi método. La mayoría de las manipulaciones de listas diferentes en el nivel kernel son realizadas por el mismo código (muy optimizado), por lo que tratar de obligar a MMA a hacer las cosas de cierta manera (que puede ser correcto/óptimo en otros idiomas) la mayoría de las veces conduce a gastos generales. – Timo

+0

Estaba haciendo mis pruebas con V8 en OS X. –

2

Still:

k= Partition[[email protected][{#, {x, y, z}}], 4]& 

[email protected] {{a, 1, 2}, {b, 2, 3}, {c, 3, 4}} 

(* 
-> {{a, 1, 2, x}, {b, 2, 3, y}, {c, 3, 4, z}} 
*) 
+0

Haz esos cinco enfoques. Este es como una salchicha: puedes comerlo, pero no quieres ver cómo está hecho :) –

3

¿Qué tal esto?

pos = 4; 
MapThread[Insert[#1, #2, pos] &, {array, column}] 
3

I (a veces) para transponer gusta con Aplanar, ya que trabaja con una matriz 'desigual'.

Map[Flatten, Flatten[{array, column}, {2}]] 

dando

{{a, 1, 2, x}, {b, 2, 3, y}, {c, 3, 4, z}}

Pero si, por ejemplo, la columna tiene sólo 2 elementos

column2 = {x, y}; 
Map[Flatten, Flatten[{array, column2}, {2}]] 

dando

{{a, 1, 2, x}, {b, 2, 3, y}, {c, 3, 4}}

(Transposición no funcionará aquí)

5

Aquí está mi trate de usar Ingreso

In[11]:= Join[array,List/@column,2] 
Out[11]= {{a,1,2,x},{b,2,3,y},{c,3,4,z}} 

podría ser comparable a la más rápida entre los programas antes mencionados.

+0

+1 ¡Muy bonito! Claro y directo. –

+0

Me sorprende que el método 'Join 'ya no esté en esta página, ya que parece ser una de las maneras más naturales (y eficientes) de hacerlo. +1 –

1

Aunque no es tan práctico o eficiente como algunos de los métodos existentes, aquí hay dos más que añadir a la lista:

ArrayPad[array, {0,{0,1}}, List /@ column] 

PadRight[array, Dimensions[array] + {0, 1}, List /@ column] 
Cuestiones relacionadas