Jak tworzyć tablice z tablicy [zamknięte]

33

Jestem początkującym w JavaScript i próbuję utworzyć dwie różne tablice z wartościami z jednej głównej tablicy.

Moja główna tablica wygląda następująco:

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 ]

I muszę utworzyć dwie tablice, najpierw wyglądające jak:

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]

(pierwsza i druga wartość)

a po drugie:

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]

(pierwsza i trzecia wartość)

Próbuję splicować, filtrować itp., Ale nie wiem, jak zacząć.

Nie jest konieczne napisanie mi dokładnego rozwiązania, a jedynie kroki, jak to zrobić.

Dominik Lev
źródło
Dziękuję bardzo za wspaniałe odpowiedzi. Działają świetnie. Mogę mieć jedno pytanie na przyszłość. Czy można to zrobić, aby nie było przymocowane do dwóch pól? Ale nawet trzy, cztery itd.?
Dominik Lev
3
Jaki faktyczny problem próbujesz tutaj rozwiązać? Wydaje się prawdopodobne, że lepszym rozwiązaniem jest użycie tablicy obiektów.
BlueRaja - Danny Pflughoeft
Sugestia: zamiast mieć wyraźne kolejne lata w tablicy, możesz mieć rok domyślny z danego punktu początkowego. Następnie potrzebujesz tylko jednego skalarnego punktu początkowego, a rok dla dowolnego elementu jest znany na podstawie jego indeksu tablicowego. (Działa tylko wtedy, gdy lata są zawsze ciągłe i rosnące, jak w tym przykładzie. Ale ładnie upraszcza to od szeregu par do szeregu pierwotnych liczb).
Peter Cordes

Odpowiedzi:

29

Możesz zastosować podejście dynamiczne i uzyskać wszystkie elementy tablicy po wartości klucza dla każdej nowej tablicy.

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
źródło
Dziękuję bardzo za świetną odpowiedź. Czy mogę zadać pytanie na przyszłość? Czy można to naprawić nie tylko na 2 tablicach, ale także na więcej?
Dominik Lev
1
można zastąpić [first, second]z arrayi masz tablice ze wszystkimi kolumnami danych, jak tablice.
Nina Scholz
2
Zamiast tego raczej powolnego r[i] = r[i] || []należy użyć Array.from({length: (data[0]?.length ?? 1) - 1}, () => [])początkowej wartości akumulatora
Bergi
3
@NinaScholz Nie, miałem na myśli, że sprawdzasz, czy r[i]istnieje w każdej iteracji pętli, podczas gdy możesz po prostu utworzyć niezbędne tablice wyników poza reducewywołaniem.
Bergi
1
@Klaycon Nie, dostęp do tablicy poza jej granicami jest bardzo wolny, więc „sprawdź, czy już istnieje” nie działa dobrze. Mój komentarz nie miał martwić się wydajnością, ale preferował czysty i przewidywalny (poprawny) kod. Najpierw napisałem „raczej brzydki i powolny”, zanim zdałem sobie sprawę, że moja sugestia, która wyraźnie mówi, że radzenie sobie z pustą skrzynką nie jest prawdziwa.
Bergi
14

Możesz użyć .map()do iteracji swoich danych i użyć Destrukturyzacji tablicy, aby uzyskać pożądane dane wyjściowe:

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
źródło
Dziękuję bardzo za świetną odpowiedź. Czy mogę zadać pytanie na przyszłość? Czy można to naprawić nie tylko na 2 tablicach, ale także na więcej?
Dominik Lev
1
@DominikLev W takim przypadku możesz użyć odpowiedzi opublikowanej przez Ninę. To jest dobre.
Mohammad Usman,
1
Można to uogólnić, używając składni parametru rest do([year, ...values]) => [year, values[n]]
JollyJoker
@JollyJoker - powinieneś zamieścić to jako odpowiedź, to naprawdę miłe i zwięzłe uogólnione rozwiązanie
Filip Milovanović
@ FilipMilovanović Zrobiłem już stackoverflow.com/a/60166014/7126740
JollyJoker
6

Możesz użyć Array.prototype.forEachdo iteracji elementów oryginalnej tablicy, a następnie utwórz nowe elementy i wepchnij je do nowych tablic:

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

Wynik:

wprowadź opis zdjęcia tutaj


Dynamiczne generowanie naszych tablic, dzięki czemu rozwiązanie działa bez względu na liczbę elementów oryginalnych tablic:

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

Wynik: wprowadź opis zdjęcia tutaj

Ismael Padilla
źródło
Dziękuję bardzo za świetną odpowiedź. Czy mogę zadać pytanie na przyszłość? Czy można to naprawić nie tylko na 2 tablicach, ale także na więcej?
Dominik Lev
1
Możliwe jest dynamiczne generowanie tablic bez wcześniejszej wiedzy o tym, ile elementów będą miały oryginalne tablice. Spójrz na moją zredagowaną odpowiedź :)
Ismael Padilla
4

Przede wszystkim macie tablicę na początku. Możesz ustawić maptę tablicę na dwie różne tablice, używając destructuringw zwięzły sposób każdej wartości z podrzędnych:

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
źródło
4

Zapętlaj główną tablicę i zwróć nową tablicę, używając stałych wartości indeksu, aby uzyskać dostęp do wartości tablic podrzędnych.

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
źródło
3

Możesz użyć funkcji zmniejsz w następujący sposób, która iteruje tylko raz:

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
źródło
Dlaczego CSS w tej odpowiedzi?
Joshua Fox
1
@JoshuaFox tylko dla zwiększenia wysokości konsoli.
Ele
3

Proszę bardzo

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
źródło
2

Użyłem map for loop, dwóch tablic do wypchnięcia potrzebnych wartości.

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
źródło
1

inne rozwiązanie :

 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]]]). redukcja ((a, b) => a.concat (b), [])

Cem Tuğut
źródło
1

Jeśli chodzi o ogólne rozwiązanie, myślę, że budowanie tablicy indeksów dla kolumn wartości daje prosty sposób mapowania pełnych danych na pożądane tablice.

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

daje tablicę indeksów minus jedna kolumna, która była rokiem, i

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

daje tablicę, którą chcesz dla kolumny n-tej wartości. Więc:

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
źródło
0

Inne rozwiązanie dla tablic wejściowych o ogólnej długości.

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
źródło
0

Skorzystaj z tego rozwiązania, aby wykonać dowolną ogólną kombinację z istniejącej macierzy wielowymiarowej. Musisz jawnie przekazać indeks przedmiotów do wybrania, a to czyni go ogólnym.

    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
źródło