Как объединить несколько массивов в javascript?

Я хочу объединить несколько массивов в один массив.

Я попробовал _.zip из библиотеки лодаш, но это не то, что мне нужно.

Вот массивы:

var arr1 = [
    'a', 'b'
];
var arr2 = [
    'c', 'd'
];
var arr3 = [
    'e'
];

И я хочу этот вывод:

var result = [
    ['a', 'c', 'e'],
    ['a', 'd', 'e'],
    ['b', 'c', 'e'],
    ['b', 'd', 'e']
];

Этого добились бы три вложенных цикла.

user47589 29.05.2019 22:10

Нужно ли работать для произвольного количества начальных массивов?

jwatts1980 29.05.2019 22:11

Я нашел этот смысл, который использует lodash, который может оказаться полезным. gist.github.com/wassname/a882ac3981c8e18d2556 Используйте комбинированную функцию с разбросом 3 массивов combinations([...a1, ...a2, ...a3], 3). Или декартово произведение, как сказал другой человек.

Anthony Z 29.05.2019 22:13

То, что вы ищете, называется «Декартово произведение». Здесь есть решения: stackoverflow.com/questions/12303989/…

GaloisGirl 29.05.2019 22:14

@RobG в теме, на которую я ссылаюсь, есть много ответов, большинство из которых не использует какие-либо внешние библиотеки.

GaloisGirl 29.05.2019 23:08
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
5
203
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Если вы ожидаете, что у вас всегда будет одинаковое количество массивов, я нахожу это более читаемым, хотя и немного избыточным:

let arr1 = [
  'a', 'b'
];
let arr2 = [
  'c', 'd'
];
let arr3 = [
  'e'
];

let result = arr1.flatMap(one =>
    arr2.flatMap(two =>
        arr3.map(three => [one, two, three])));
console.info(result);

Если вы не всегда ожидаете 3 массива или предпочитаете общую функцию для умножения произвольного количества массивов:

let arr1 = [
  'a', 'b'
];
let arr2 = [
  'c', 'd'
];
let arr3 = [
  'e'
];

let multiply = (...arrays) =>
    arrays.reduce((results, array) =>
        results.flatMap(result => array.map(a => [...result, a])), ['']);

let results = multiply(arr1, arr2, arr3);
console.info(results);

Второй не работает. ...result на самом деле распространяет строку. Поскольку это строки с одним символом, это работает. Если вы попробуете с [ 'aa', 'bb' ], вы увидите это

adiga 01.06.2019 15:09

хороший улов. фиксированный.

junvar 01.06.2019 20:08

Как уже отмечали другие, это называется декартовым произведением ваших массивов. Мне проще построить его, сложив (reducing) над тем, который берет произведение двух массивов.

const product = (xs, ys) => 
  xs .flatMap (x => ys .map (y => [x, y] .flat () ) )

const productAll = (...xss) => 
  xss .reduce (product)

console .log (
  productAll ( ['a', 'b'], ['c', 'd'], ['e'])
)

Если ваша среда не поддерживает поддержите flat и flatmap, их довольно легко скрыть.

Если вы хотите предоставить массивы внутри одного массива [['a', 'b'], ['c', 'd'], ['e']], а не по отдельности, просто замените ...xss на xss.

Несколько человек уже упомянули, что ваш вопрос является дубликатом этот вопрос. Итак, вы можете посмотреть там рекомендуемое решение.

Я просто хотел добавить еще одно функциональное решение, которое можно произвольно комбинировать. Функция listProduct в этом случае имеет тип listProduct :: [[a]] -> [a] -> [[a]], что означает, что она принимает (как минимум) двумерный массив в качестве первого аргумента и возвращает его. Вот почему функция singletonize необходима для преобразования первого массива в двумерный массив.

Как показано ниже, вы можете легко комбинировать вызовы этой функции, чтобы получить произведение n (n ≥ 2) списка, если хотите.

const singletonize = l => l.map(x => [x])
const listProduct = (ls, list) => 
  ls.reduce((r, l) => {
      combinations = list.map(x => l.concat(x))
      return r.concat(combinations)
  }, [])
  
// The three arrays of your example
const a_1 = ['a', 'b'];
const a_2 = ['c', 'd'];
const a_3 = ['e'];
console.info(listProduct(listProduct(singletonize(a_1), a_2), a_3))

// Another example with five arrays
const a_4 = ['f', 'g', 'h'];
const a_5 = ['i'];

console.info(listProduct(listProduct(listProduct(listProduct(singletonize(a_1), a_2), a_3), a_4), a_5))
Ответ принят как подходящий

Вы можете взять функцию декартова произведения заданных массивов.

const cartesian = (...p) =>
        p.reduce((a, b) => a.reduce((r, v) => r.concat(b.map(w => [].concat(v, w))), []));

var a = ['a', 'b'],
    b = ['c', 'd'],
    c = ['e'];
    result = cartesian(a, b, c);

result.forEach(a => console.info(...a));

Другие вопросы по теме