0

Wondering how to take a nested array such as this:

var arr = [
    1,
    [ 
        2, 3, 4, 
        [ 
            5, 6, 7, 8, 
            [ 9, 10 ], 
            [ 11, 12 ]
        ], 
        [ 13, 14 ] 
    ] 
]   

And apply a grouping function:

function group(arr) {

}

Such that it converts arr into the following:

var output = [
  [1, 2, 5, 13, 9, 11],
  [1, 2, 5, 13, 9, 12],
  [1, 2, 5, 13, 10, 11],
  [1, 2, 5, 13, 10, 12]

  [1, 3, 5, 13, 9, 11],
  [1, 3, 5, 13, 9, 12],
  [1, 3, 5, 13, 10, 11],
  [1, 3, 5, 13, 10, 12],

  [1, 3, 6, 13, 9, 11],
  [1, 3, 6, 13, 9, 12],
  [1, 3, 6, 13, 10, 11],
  [1, 3, 6, 13, 10, 12],

  [1, 3, 7, 13, 9, 11],
  [1, 3, 7, 13, 9, 12],
  [1, 3, 7, 13, 10, 11],
  [1, 3, 7, 13, 10, 12],

  ...

  [1, 4, 5, 13, 9, 11],
  [1, 4, 5, 13, 9, 12],
  [1, 4, 5, 13, 10, 11],
  [1, 4, 5, 13, 10, 12],

  ...
]

Basically it flattens the array, or you could say gets every combination of all sub arrays, and returns them in a flat list. Breaking my head on this one.

Cerbrus
  • 70,800
  • 18
  • 132
  • 147
Lance
  • 75,200
  • 93
  • 289
  • 503

1 Answers1

0

Looks pretty simple - you want to apply the cartesian product on all of the nesting levels, and recursively flatten the elements.

However, your input is a bit weird, it would have been easier (and more flexible!) if you had used

var arr = [
    [ 1 ],
    [
        [ 2, 3, 4 ],
        [
            [ 5, 6, 7, 8 ],
            [ 9, 10 ],
            [ 11, 12 ]
        ],
        [ 13, 14 ]
    ]
];

So now it requires some slicing to split the two parts of each array:

function flatten(arr) { return [].concat(...arr); }
function group(arr) {
    const i = arr.findIndex(Array.isArray)
    return i < 0
      ? arr
      : cartesian([arr.slice(0, i), ...arr.slice(i).map(group)]).map(flatten);
}

With the flexible input format, it would be just

function group(arr) {
  return arr.every(Array.isArray) // or even Array.isArray(arr[0])?
    ? cartesian(arr.map(group)).map(flatten) // group simply every element - even the first
    : arr;
}
Bergi
  • 630,263
  • 148
  • 957
  • 1,375