Cómo crear matrices desde la matriz [cerrado]

33

Soy un principiante de JavaScript y estoy tratando de hacer dos matrices diferentes con valores de una matriz principal.

Mi matriz principal se ve así:

0: Array(3) [ 2011, 127072.7, 51584 ]
1: Array(3) [ 2012, 125920.3, 59974 ]
2: Array(3) [ 2013, 129305.4, 15468 ]
3: Array(3) [ 2014, 135364, 84554 ]
4: Array(3) [ 2015, 136757, 98754 ]
5: Array(3) [ 2016, 155653.5, 155548 ]
6: Array(3) [ 2017, 164130.5, 284848 ]

Y necesito crear dos matrices, primero como:

0: Array(2) [ 2011, 127072.7]
1: Array(2) [ 2012, 125920.3]
2: Array(2) [ 2013, 129305.4]
3: Array(2) [ 2014, 135364]
4: Array(2) [ 2015, 136757]
5: Array(2) [ 2016, 155653.5]
6: Array(2) [ 2017, 164130.5]

(primer y segundo valor)

y segundo como:

0: Array(2) [ 2011, 51584]
1: Array(2) [ 2012, 59974]
2: Array(2) [ 2013, 15468]
3: Array(2) [ 2014, 84554]
4: Array(2) [ 2015, 98754]
5: Array(2) [ 2016, 155548]
6: Array(2) [ 2017, 284848]

(primer y tercer valor)

Intento empalmar, filtrar, etc. pero no sé cómo comenzar.

No es necesario que me escriba una solución exacta, pero solo explica cómo hacerlo.

Dominik Lev
fuente
Muchas gracias por las excelentes respuestas. Funcionan muy bien Puedo tener una pregunta para el futuro. ¿Se puede hacer para que no esté fijado a dos campos? ¿Pero incluso tres, cuatro, etc.?
Dominik Lev
3
¿Cuál es el problema real que estás tratando de resolver aquí? Parece probable que usar una matriz de objetos sea la mejor opción.
BlueRaja - Danny Pflughoeft
Sugerencia: en lugar de tener años explícitos consecutivos en su matriz, podría hacer que el año sea implícito desde un punto de partida dado. Entonces solo necesita un punto de inicio escalar, y el año para cualquier elemento se conoce en función de su índice de matriz. (Solo funciona si sus años son siempre contiguos y en orden ascendente como este ejemplo. Pero se simplifica muy bien de una matriz de pares a solo una matriz de números primitivos).
Peter Cordes

Respuestas:

29

Podría adoptar un enfoque dinámico y obtener todos los elementos de la matriz después del valor clave para cada nueva matriz.

var data = [[2011, 127072.7, 51584], [2012, 125920.3, 59974], [2013, 129305.4, 15468], [2014, 135364, 84554], [2015, 136757, 98754], [2016, 155653.5, 155548], [2017, 164130.5, 284848]],
    [first, second] = data.reduce(
        (r, [k, ...a]) => {
            a.forEach((v, i) => r[i].push([k, v]));
            return r;
        },
        Array.from({ length: Array.isArray(data[0]) ? data[0].length - 1 : 0 }, () => [])
    );

console.log(first);
console.log(second);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Nina Scholz
fuente
Muchas gracias por una gran respuesta. ¿Puedo tener una pregunta para el futuro? ¿Es posible arreglarlo no solo en 2 matrices sino también en más?
Dominik Lev
1
podría reemplazar [first, second]con arrayy obtendrá matrices con todas las columnas de los datos como matrices.
Nina Scholz
2
En lugar de eso bastante lento r[i] = r[i] || [], solo debe usarlo Array.from({length: (data[0]?.length ?? 1) - 1}, () => [])para el valor inicial del acumulador
Bergi
3
@NinaScholz No, quise decir que está comprobando si r[i]existe en cada iteración de bucle, mientras que simplemente podría crear las matrices de resultados necesarias fuera de la reducellamada.
Bergi
1
@Klaycon No, los accesos a la matriz fuera de los límites de la matriz son muy lentos, por lo que "verificar si ya existe" no funciona bien. Mi comentario no pretendía preocuparme por el rendimiento, sino preferir un código limpio y predecible (correcto). Primero escribí "bastante feo y lento" antes de darme cuenta de que mi sugerencia que hace explícito tratar el caso vacío tampoco es una verdadera belleza.
Bergi
14

Puede usar .map()para iterar sobre sus datos y usar algo de Destrucción de matriz para obtener la salida deseada:

const data = [
  [ 2011, 127072.7, 51584 ],
  [ 2012, 125920.3, 59974 ],
  [ 2013, 129305.4, 15468 ],
  [ 2014, 135364, 84554 ],
  [ 2015, 136757, 98754 ],
  [ 2016, 155653.5, 155548 ],
  [ 2017, 164130.5, 284848 ]
];

const arr1 = data.map(([year, val]) => ([year, val]));
const arr2 = data.map(([year, _, val]) => ([year, val]));

console.log(arr1);
console.log(arr2);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Mohammad Usman
fuente
Muchas gracias por una gran respuesta. ¿Puedo tener una pregunta para el futuro? ¿Es posible arreglarlo no solo en 2 matrices sino también en más?
Dominik Lev
1
@DominikLev En ese caso, puede usar la respuesta publicada por Nina. Es una buena
Mohammad Usman
1
Esto se puede generalizar usando la sintaxis del parámetro rest para([year, ...values]) => [year, values[n]]
JollyJoker
@JollyJoker: debe publicar eso como respuesta, esa es una solución generalizada muy agradable y concisa
Filip Milovanović
@ FilipMilovanović Ya hice stackoverflow.com/a/60166014/7126740
JollyJoker
6

Puede usar Array.prototype.forEachpara iterar sobre los elementos de la matriz original, luego crear los nuevos elementos e insertarlos en nuevas matrices:

var original = [[ 2011, 127072.7, 51584 ], [ 2012, 125920.3, 59974 ], [ 2013, 129305.4, 15468 ]]

var array1 = []
var array2 = []

original.forEach(item => {
  array1.push([item[0], item[1]]);
  array2.push([item[0], item[2]]);
});

console.log(array1);
console.log(array2);

Salida:

ingrese la descripción de la imagen aquí


Generando nuestras matrices dinámicamente para que la solución funcione sin importar cuántos elementos tengan las matrices originales:

var original = [
  [2011, 127072.7, 51584, 1, 2, 3],
  [2012, 125920.3, 59974, 4, 5, 6],
  [2013, 129305.4, 15468, 7, 8, 9]
]

// Array of arrays
var myArray = []

// Fill it with empty arrays
for (var i = 0; i < original[0].length - 1; i++)
  myArray.push([])

// Iterate over original
// For each original, insert the first and i-th element into our array of arrays
original.forEach(item => {
  for (var i = 1; i < item.length; i++) {
    myArray[i - 1].push([item[0], item[i]]);
  }
});

console.log(myArray);

Salida: ingrese la descripción de la imagen aquí

Ismael Padilla
fuente
Muchas gracias por una gran respuesta. ¿Puedo tener una pregunta para el futuro? ¿Es posible arreglarlo no solo en 2 matrices sino también en más?
Dominik Lev
1
Es posible generar las matrices dinámicamente sin saber de antemano cuántos elementos tendrán las matrices originales. Echa un vistazo a mi respuesta editada :)
Ismael Padilla
4

En primer lugar, tiene una matriz de matrices al principio. Puede mapusar esta matriz en dos matrices diferentes destructuringpara obtener cada valor de las submatrices de manera concisa:

const data = [
  [ 2011, 127072.7, 51584 ],
  [ 2012, 125920.3, 59974 ],
  [ 2013, 129305.4, 15468 ],
  [ 2014, 135364, 84554 ],
  [ 2015, 136757, 98754 ],
  [ 2016, 155653.5, 155548 ],
  [ 2017, 164130.5, 284848 ],
];

const array1 = data.map(([first, second, third]) => [first, second]);
const array2 = data.map(([first, second, third]) => [first, third]);

console.log(JSON.stringify(array1));
console.log(JSON.stringify(array2));

Alberto Trindade Tavares
fuente
4

Recorra la matriz principal y devuelva una nueva matriz utilizando valores de índice fijos para acceder a los valores de sus matrices secundarias.

const multiDimArr = [
  [2011, 127072.7, 51584],
  [2012, 125920.3, 59974],
  [2013, 129305.4, 15468],
  [2014, 135364, 84554],
  [2015, 136757, 98754],
  [2016, 155653.5, 155548],
  [2017, 164130.5, 284848],
]

const arr1= multiDimArr.map(x=>[x[0],x[1]]);
const arr2= multiDimArr.map(x=>[x[0],x[2]]);

console.log(arr1)
console.log(arr2)

Eugen Sunic
fuente
3

Puede usar la función reducir como sigue, que itera solo una vez:

let matrix = [[ 2011, 127072.7, 51584 ],[ 2012, 125920.3, 59974 ],[ 2013, 129305.4, 15468 ],[ 2014, 135364, 84554 ],[ 2015, 136757, 98754 ],[ 2016, 155653.5, 155548 ],[ 2017, 164130.5, 284848 ]];

let result = matrix.reduce((a, [year, k, v]) => {
  a.second.push([year, k]);
  a.third.push([year, v]);
  return a;
}, {second: [], third: []});

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Ele
fuente
¿Por qué el CSS en esta respuesta?
Joshua Fox
1
@JoshuaFox solo para expandir la altura de la consola.
Ele
3

Aqui tienes

let values = [[ 2011, 127072.7, 51584 ],[ 2012, 125920.3, 59974 ],[ 2013, 129305.4, 15468 ],[ 2014, 135364, 84554 ],[ 2015, 136757, 98754 ],[ 2016, 155653.5, 155548 ],[ 2017, 164130.5, 284848 ]];

let chunk1 = values.map(arr1 => {
  return [arr1[0], arr1[1]]
});
let chunk2 = values.map(arr1 => {
  return [arr1[0], arr1[2]]
})

console.log("Chunk 1", chunk1);
console.log("Chunk 2", chunk2);

Muhammad Zeeshan
fuente
2

He usado map for loop, dos matrices para empujar los valores necesarios.

let point_table = []
let integer_table = []
const historical_table = [
  [2011, 127072.7, 51584],
  [2012, 125920.3, 59974],
  [2013, 129305.4, 15468],
  [2014, 135364, 84554],
  [2015, 136757, 98754],
  [2016, 155653.5, 155548],
  [2017, 164130.5, 284848]
]
historical_table.map(row => {
  point_table.push([row[0], row[1]])
  integer_table.push([row[0], row[2]])
})
console.log(point_table, integer_table)

iEfimoff
fuente
1

otra solución :

 const original= [  [ 2011, 127072.7, 51584 ], [ 2012, 125920.3, 59974 ],[ 2013, 129305.4, 15468 ],  [ 2014, 135364, 84554 ],  [ 2015, 136757, 98754 ],  [ 2016, 155653.5, 155548 ],  [ 2017, 164130.5, 284848 ]];

original.map (x => [[x [0], x [1]], [x [0], x [2]]]) .reduce ((a, b) => a.concat (b), [])

Cem Tuğut
fuente
1

Para la solución genérica, creo que construir una matriz de índices para las columnas de valor le brinda una forma simple de asignar los datos completos a las matrices que desea.

[...data[0].keys()].slice(0,-1)

le brinda una variedad de índices, menos la columna que fue el año, y

n => data.map(([year, ...values]) => [year, values[n]])

le da la matriz que desea para la enésima columna de valor. Entonces:

var data = [[2011, 127072.7, 51584], [2012, 125920.3, 59974], [2013, 129305.4, 15468], [2014, 135364, 84554], [2015, 136757, 98754], [2016, 155653.5, 155548], [2017, 164130.5, 284848]]

const yearArrays = arr => [...arr[0].keys()].slice(0,-1)
       .map(arr.map(([year, ...values]) => [year, values[n]]))

console.log(yearArrays(data));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Bromista alegre
fuente
0

Otra solución para matrices de entrada de longitud genérica.

const input = [[1,11,111,1111],[2,22,222,2222]];

const result = input.reduce((accumulator, [head, ...tail]) => {
  tail.forEach((item, index) => {
    accumulator[index] = accumulator[index] || [];
    accumulator[index].push([head, item]);
  });
  return accumulator;
}, [])

console.log(result);

Linus
fuente
0

Use esta solución para hacer cualquier combinación genérica a partir de una matriz multidimensional existente. Tienes que pasar el índice de elementos para elegir explícitamente y eso es lo que lo hace genérico.

    const multiDimArr = [
      [2011, 127072.7, 51584],
      [2012, 125920.3, 59974],
      [2013, 129305.4, 15468],
      [2014, 135364, 84554],
      [2015, 136757, 98754],
      [2016, 155653.5, 155548],
      [2017, 164130.5, 284848],
    ]


    function arrayCombo (idxA, idxB){
      return multiDimArr.map(x=>[x[idxA],x[idxB]]);
    }

    console.log(arrayCombo(0, 1));
    console.log(arrayCombo(0, 2));
    console.log(arrayCombo(1, 2));

rach8garg
fuente