Как создать массивы из массива [закрыто]

33

Я новичок в JavaScript и пытаюсь создать два разных массива со значениями из одного основного массива.

Мой основной массив выглядит так:

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 ]

И мне нужно создать два массива, сначала выглядя так:

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]

(первое и второе значение)

а второй вроде:

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]

(первое и третье значение)

Я пытаюсь сращивать, фильтровать и т. Д., Но я не знаю, как начать.

Не нужно писать мне точное решение, а только шаги, как это сделать.

Доминик Лев
источник
Большое спасибо за отличные ответы. Они отлично работают. У меня может быть один вопрос на будущее. Можно ли сделать так, чтобы оно не фиксировалось на двух полях? Но даже три, четыре и т. Д.?
Доминик Лев
3
Какую реальную проблему вы пытаетесь решить здесь? Вероятно, использование массива объектов является лучшим вариантом.
BlueRaja - Дэнни Пфлюгофт
Предложение: вместо явных последовательных лет в вашем массиве, вы можете иметь неявный год с заданной начальной точки. Тогда вам понадобится только одна скалярная начальная точка, и год для любого элемента известен по индексу массива. (Работает только в том случае, если ваши годы всегда являются смежными и в порядке возрастания, как в этом примере. Но он значительно упрощает переход от массива пар к массиву примитивных чисел.)
Питер Кордес

Ответы:

29

Вы можете использовать динамический подход и получить все элементы массива после значения ключа для каждого нового массива.

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

Нина Шольц
источник
Большое спасибо за отличный ответ. Могу ли я задать вопрос на будущее? Можно ли сделать так, чтобы это фиксировалось не только на 2 массивах, но и на большем?
Доминик Лев
1
Вы можете заменить [first, second]на arrayи вы получите массивы со всеми столбцами данных в виде массивов.
Нина Шольц
2
Вместо этого довольно медленно, r[i] = r[i] || []вы должны просто использовать Array.from({length: (data[0]?.length ?? 1) - 1}, () => [])для начального значения аккумулятора
Берги
3
@NinaScholz Нет, я имел в виду, что вы проверяете, r[i]существует ли в каждой итерации цикла, тогда как вы можете просто создать необходимые массивы результатов вне reduceвызова.
Берги
1
@Klaycon Нет, доступ к массиву за пределами массива очень медленный, поэтому проверка, если он уже существует, не работает должным образом. Мой комментарий предназначался не для того, чтобы беспокоиться о производительности, а для того, чтобы предпочесть чистый и предсказуемый (правильный) код. Сначала я написал «довольно некрасиво и медленно», прежде чем понял, что мое предложение, которое делает ясным обращение с пустым регистром, также не является настоящей красотой.
Берги
14

Вы можете использовать .map()для перебора ваших данных и использовать некоторую структуру массива для получения желаемого результата:

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

Мухаммед Усман
источник
Большое спасибо за отличный ответ. Могу ли я задать вопрос на будущее? Можно ли сделать так, чтобы это фиксировалось не только на 2 массивах, но и на большем?
Доминик Лев
1
@DominikLev В этом случае вы можете использовать ответ, размещенный Ниной. Это хороший.
Мухаммед Усман
1
Это можно обобщить, используя синтаксис параметра rest для([year, ...values]) => [year, values[n]]
JollyJoker,
@JollyJoker - вы должны опубликовать это как ответ, это действительно хорошее и краткое обобщенное решение
Филипп Милованович
@ FilipMilovanović Я уже сделал stackoverflow.com/a/60166014/7126740
JollyJoker
6

Вы можете использовать Array.prototype.forEachдля перебора элементов исходного массива, а затем создавать новые элементы и помещать их в новые массивы:

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

Вывод:

введите описание изображения здесь


Динамическое создание наших массивов, чтобы решение работало независимо от того, сколько элементов имеют исходные массивы:

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

Вывод: введите описание изображения здесь

Исмаэль Падилья
источник
Большое спасибо за отличный ответ. Могу ли я задать вопрос на будущее? Можно ли сделать так, чтобы это фиксировалось не только на 2 массивах, но и на большем?
Доминик Лев
1
Можно динамически генерировать массивы, не зная заранее, сколько элементов будет в исходных массивах. Взгляните на мой отредактированный ответ :)
Исмаэль Падилья
4

Прежде всего, у вас есть массив массивов в начале. Вы можете использовать mapэтот массив для двух разных массивов, destructuringчтобы получить каждое значение из подмассивов в сжатой форме:

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

Альберто Триндаде Таварес
источник
4

Выполните цикл по основному массиву и верните новый массив, используя фиксированные значения индекса для доступа к значениям ваших дочерних массивов.

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)

Евгений Сунич
источник
3

Вы можете использовать функцию Reduce как следует, которая повторяется только один раз:

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
источник
Почему CSS в этом ответе?
Джошуа Фокс
1
@JoshuaFox просто для увеличения высоты консоли.
Эле
3

Ну вот

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

Мухаммед Зеешан
источник
2

Я использовал карту для цикла, два массива, чтобы выдвинуть необходимые значения.

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
источник
1

другое решение:

 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), [])

Джем Тугут
источник
1

Для общего решения я думаю, что построение массива индексов для столбцов значений дает вам простой способ сопоставления полных данных с массивами, которые вы хотите.

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

дает вам массив индексов, минус один столбец, который был годом, и

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

дает вам массив, который вы хотите для столбца n-го значения. Так:

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
источник
0

Другое решение для входных массивов общей длины.

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

Линус
источник
0

Используйте это решение для создания любой общей комбинации из существующего многомерного массива. Вы должны явно передать индекс предметов для выбора, и это делает его универсальным.

    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
источник