Comment créer des tableaux à partir d'un tableau [fermé]

33

Je suis un débutant JavaScript et j'essaie de créer deux tableaux différents avec des valeurs à partir d'un tableau principal.

Mon tableau principal ressemble à:

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 ]

Et j'ai besoin de créer deux tableaux, ressemblant d'abord à:

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]

(première et deuxième valeur)

et deuxième comme:

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]

(première et troisième valeur)

J'essaie d'épissure, de filtrage, etc. mais je ne sais pas par où commencer.

Il n'est pas nécessaire de m'écrire une solution exacte, mais seulement des étapes pour le faire.

Dominik Lev
la source
Merci beaucoup pour les bonnes réponses. Ils fonctionnent très bien. J'ai peut-être une question pour l'avenir. Peut-on le faire pour qu'il ne soit pas fixé sur deux champs? Mais même trois, quatre, etc.?
Dominik Lev
3
Quel est le véritable problème que vous essayez de résoudre ici? Il semble probable que l'utilisation d'un tableau d'objets soit la meilleure option.
BlueRaja - Danny Pflughoeft
Suggestion: au lieu d'avoir des années consécutives explicites dans votre tableau, vous pourriez avoir l'année implicite à partir d'un point de départ donné. Ensuite, vous n'avez besoin que d'un point de départ scalaire, et l'année de tout élément est connue en fonction de son index de tableau. (Ne fonctionne que si vos années sont toujours contiguës et dans l'ordre croissant comme cet exemple. Mais simplifie bien d'un tableau de paires à un tableau de nombres primitifs seulement.)
Peter Cordes

Réponses:

29

Vous pouvez adopter une approche dynamique et obtenir tous les éléments du tableau après la valeur de clé pour chaque nouveau tableau.

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
la source
Merci beaucoup pour une excellente réponse. Puis-je avoir une question pour l'avenir? Est-il possible de le faire fixer non seulement sur 2 baies mais aussi sur plus?
Dominik Lev
1
vous pouvez remplacer [first, second]par arrayet vous obtenez des tableaux avec toutes les colonnes des données sous forme de tableaux.
Nina Scholz
2
Au lieu de cela plutôt lent, r[i] = r[i] || []vous devez simplement utiliser Array.from({length: (data[0]?.length ?? 1) - 1}, () => [])la valeur initiale de l'accumulateur
Bergi
3
@NinaScholz Non, je voulais dire que vous vérifiez s'il r[i]existe dans chaque itération de boucle, alors que vous pouvez simplement créer les tableaux de résultats nécessaires en dehors de l' reduceappel.
Bergi
1
@Klaycon Non, les accès aux tableaux en dehors des limites du tableau sont très lents, donc "vérifier s'il existe déjà" ne fonctionne pas bien. Mon commentaire n'était pas destiné à se soucier des performances, mais à préférer un code propre et prévisible (correct). J'ai d'abord écrit "plutôt moche et lent" avant de réaliser que ma suggestion qui rend explicite le traitement du cas vide n'est pas non plus une vraie beauté.
Bergi
14

Vous pouvez utiliser .map()pour itérer sur vos données et utiliser une certaine restructuration de tableau pour obtenir la sortie souhaitée:

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
la source
Merci beaucoup pour une excellente réponse. Puis-je avoir une question pour l'avenir? Est-il possible de le faire fixer non seulement sur 2 baies mais aussi sur plus?
Dominik Lev
1
@DominikLev Dans ce cas, vous pouvez utiliser la réponse publiée par Nina. C'est une bonne chose.
Mohammad Usman
1
Cela peut être généralisé en utilisant la syntaxe des paramètres de repos pour([year, ...values]) => [year, values[n]]
JollyJoker
@JollyJoker - vous devriez poster cela comme une réponse, c'est une solution généralisée très agréable et concise
Filip Milovanović
@ FilipMilovanović J'ai déjà fait stackoverflow.com/a/60166014/7126740
JollyJoker
6

Vous pouvez utiliser Array.prototype.forEachpour parcourir les éléments du tableau d'origine, puis créer les nouveaux éléments et les pousser dans de nouveaux tableaux:

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);

Production:

entrez la description de l'image ici


Génération dynamique de nos tableaux afin que la solution fonctionne quel que soit le nombre d'éléments des tableaux d'origine:

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);

Production: entrez la description de l'image ici

Ismael Padilla
la source
Merci beaucoup pour une excellente réponse. Puis-je avoir une question pour l'avenir? Est-il possible de le faire fixer non seulement sur 2 baies mais aussi sur plus?
Dominik Lev
1
Il est possible de générer les tableaux dynamiquement sans savoir à l'avance combien d'éléments les tableaux originaux auront. Jetez un oeil à ma réponse modifiée :)
Ismael Padilla
4

Tout d'abord, vous avez un tableau de tableaux au début. Vous pouvez mapcréer ce tableau dans deux tableaux différents en utilisant destructuringpour obtenir chaque valeur des sous- tableaux de manière concise:

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
la source
4

Parcourez le tableau principal et renvoyez un nouveau tableau en utilisant des valeurs d'index fixes pour accéder aux valeurs de vos tableaux enfants.

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
la source
3

Vous pouvez utiliser la fonction réduire comme suit qui itère une seule fois:

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
la source
Pourquoi le CSS dans cette réponse?
Joshua Fox
1
@JoshuaFox juste pour augmenter la hauteur de la console.
Ele
3

Voici

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
la source
2

J'ai utilisé map for loop, deux tableaux pour pousser les valeurs nécessaires.

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
la source
1

une autre solution :

 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
la source
1

Pour la solution générique, je pense que la création d'un tableau d'index pour les colonnes de valeur vous donne un moyen simple de mapper les données complètes aux tableaux que vous souhaitez.

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

vous donne un tableau d'indices, moins la colonne qui était l'année, et

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

vous donne le tableau que vous voulez pour la nième colonne de valeur. Donc:

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; }

JollyJoker
la source
0

Une autre solution pour les tableaux d'entrée de longueur générique.

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
la source
0

Utilisez cette solution pour créer n'importe quelle combinaison générique à partir d'un tableau multidimensionnel existant. Vous devez passer explicitement l'index des éléments à choisir et c'est ce qui le rend générique.

    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
la source