1

I want to combine some multiple arrays into one array.

I tried _.zip of lodash library, but that's not what I want.

Here is the arrays:

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

And I want this output:

var result = [
    ['a', 'c', 'e'],
    ['a', 'd', 'e'],
    ['b', 'c', 'e'],
    ['b', 'd', 'e']
];
Emma
  • 27,428
  • 11
  • 44
  • 69
Rez
  • 514
  • 1
  • 9
  • 31
  • Three nested loops would accomplish this. –  May 29 '19 at 20:10
  • Does it need to work for an arbitrary number of starting arrays? – jwatts1980 May 29 '19 at 20:11
  • I found this gist that uses lodash that you may find useful. https://gist.github.com/wassname/a882ac3981c8e18d2556 Use the combination function with a spread of the 3 arrays `combinations([...a1, ...a2, ...a3], 3)`. Or the Cartesian product like the other person said. – Anthony Z May 29 '19 at 20:13
  • What you're looking for is called "Cartesian product". There are solutions here: https://stackoverflow.com/questions/12303989/cartesian-product-of-multiple-arrays-in-javascript – GaloisGirl May 29 '19 at 20:14
  • 1
    @RobG the thread I linked has many answers, most of them not using any external libraries. – GaloisGirl May 29 '19 at 21:08

4 Answers4

3

If you expect to always have the same number of arrays, I find this more readable though a bit redundant:

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.log(result);

If you're not always expecting 3 arrays or prefer a generic func to multiply an arbitrary number of arrays:

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.log(results);
junvar
  • 11,151
  • 2
  • 30
  • 46
  • 1
    The second one doesn't work. `...result` is actually spreading a string. Since this has strings with single character, it works. If you try with `[ 'aa', 'bb' ]` you can see it – adiga Jun 01 '19 at 13:09
  • good catch. fixed. – junvar Jun 01 '19 at 18:08
1

You could take a function for a cartesian product of the given arrays.

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.log(...a));
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

As others have noted, this is called the Cartesian Product of your arrays. I find it easier to build it by folding (reducing) over one that takes the product of two arrays.

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'])
)

If your environment doesn't support flat and flatmap, they are pretty easy to shim.

If you want to supply the arrays inside one array [['a', 'b'], ['c', 'd'], ['e']] instead of separately, just replace ...xss with xss.

Scott Sauyet
  • 49,207
  • 4
  • 49
  • 103
0

Multiple people have alread mentioned that your question is a duplicate of this question. So, you might want to have a look there for a recommended solution.

I just wanted to add another functional solution which can be arbitrarily combined. The listProduct function in this case has type listProduct :: [[a]] -> [a] -> [[a]] meaning it takes a (at least) 2-dimensional array as its first argument and returns one. That's why the singletonize function is required to convert the first array into a 2-dimensional array.

As shown below you can easily combine calls to this function to get a product of n (n ≥ 2) list if you want.

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.log(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.log(listProduct(listProduct(listProduct(listProduct(singletonize(a_1), a_2), a_3), a_4), a_5))
FK82
  • 4,907
  • 4
  • 29
  • 42