Jack Ryan
Jack Ryan

Reputation: 1318

Flatten array of objects of arrays JavaScript

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

Answers (6)

Steven
Steven

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

williamsi
williamsi

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

Ori Drori
Ori Drori

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

Jack Ryan
Jack Ryan

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

CertainPerformance
CertainPerformance

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

CRice
CRice

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

Related Questions