Reputation: 1318
I am trying to flatten an array of objects of arrays. For example, we might have something like so:
[{ numbers: [1, 2, 3] }, { numbers: [4, 5] }, { numbers: [6] }]
I would like to flatten it into:
[1, 2, 3, 4, 5, 6]
I have a working solution doing something like this:
const arr = [{ numbers: [1, 2, 3] }, { numbers: [4, 5] }, { numbers: [6] }];
const almostFlattened = arr.map((obj) => obj.numbers);
const flattened = [].concat.apply([], almostFlattened);
console.log(flattened);
Does anyone know of an easier or more performant solution here, preferably without the almostFlattened
middle step?
Upvotes: 5
Views: 9568
Reputation: 1243
For much more deeply nested array of arrays such as:
[1, 2, 3, [4, [5, [6, [7]]]]]
const flatten = (input, acc=[]) => {
return input.reduce((_, current) => {
if (Array.isArray(current)) return flatten(current, acc);
acc.push(current);
return acc;
}, []);
}
Usage:
console.log(flatten([1, 2, 3, [4, [5, [6, [7]]]]]));
Upvotes: 0
Reputation: 1606
FlatMap is great
const data = [{ numbers: [1, 2, 3] }, { numbers: [4, 5] }, { numbers: [6] }]
data.flatMap(n => n.numbers)
If you want to flatten object with arrays:
Object.values({one: [1,2,3], two: [4,5,6]}).flat()
Upvotes: 1
Reputation: 191946
You can try Array.reduce()
, and flatten the numbers' arrays by concatenating the numbers with the accumulator:
const arr = [{ numbers: [1, 2, 3] }, { numbers: [4, 5] }, { numbers: [6] }];
const result = arr.reduce((r, obj) => r.concat(obj.numbers), []);
console.log(result);
Another option is Array.flatMap()
(not supported by IE/Edge):
const arr = [{ numbers: [1, 2, 3] }, { numbers: [4, 5] }, { numbers: [6] }];
const result = arr.flatMap(obj => obj.numbers);
console.log(result);
Upvotes: 13
Reputation: 1318
I also figured I would throw this out there in case anyone is using something like lodash/underscore (did not know this function existed at the time I posted the question):
const arr = [{ numbers: [1, 2, 3] }, { numbers: [4, 5] }, { numbers: [6] }];
const flattened = _.flatten(arr, 'numbers');
console.log(flattened);
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.js"></script>
Upvotes: 0
Reputation: 370679
Use the spread syntax with reduce
:
const input = [{ numbers: [1, 2, 3] }, { numbers: [4, 5] }, { numbers: [6] }]
const output = input.reduce(((outputSoFar, { numbers }) => [...outputSoFar, ...numbers]), []);
console.log(output);
Upvotes: 1
Reputation: 32146
Why not just use what you have, but inline? There's no need to declare a middle variable almostFlattened
when you can put the .map
call as part of the arguments to .concat
:
const arr = [{ numbers: [1, 2, 3] }, { numbers: [4, 5] }, { numbers: [6] }]
const result = [].concat(...arr.map(o => o.numbers));
console.log(result)
Upvotes: 5