brandonscript
brandonscript

Reputation: 72965

Using map() and/or reduce() to simplify a forEach() statement in Node (or native JavaScript)

I've got some data:

var rows = [{
    name: "name1",
    description: "description1",
    value: 101
}, {
    name: "name2",
    description: "description2",
    value: 202
}]

Purely for fun, I'd like to turn this into a matrix of object keys containing arrays of the matching data points. Here's one-liner I got working using forEach():

var o = {}
rows.forEach(row => Object.keys(row).forEach(key => (o[key] === undefined) ? o[key] = [row[key]] : o[key].push(row[key])))

console.log(o)

/*
{
    name: ['name1', 'name2'],
    description: ['description1', 'description2'],
    value: [101, 202]
}
*/

I have a feeling I can still shorten this expression using map() and/or reduce(), but I've so far been completely stymied!

Also, let's assume the keys are consistent, but not always known.

Upvotes: 0

Views: 120

Answers (3)

robertwalsh
robertwalsh

Reputation: 171

Using lodash you can do this with

var rows = [{
    name: "name1",
    description: "description1",
    value: 101
}, {
    name: "name2",
    description: "description2",
    value: 202
}];
 
var combined = _.mergeWith(...rows, (o, s) => _.castArray(o).concat(_.castArray(s)));

console.log(combined);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>

Upvotes: 1

Thomas
Thomas

Reputation: 12647

If the keys are consistent, you can do sth like:

var matrix = Object.keys(rows[0]).reduce((o, key) => ( o[key] = rows.map(row => row[key]), o), {});

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386660

You could use Array#reduce with a short cut for checking if a property exists.

var rows = [{ name: "name1", description: "description1", value: 101 }, {  name: "name2", description: "description2", value: 202 }],
    obj = rows.reduce(
        (o, row) => (
            Object.keys(row).forEach(key => (o[key] = o[key] || []).push(row[key])),
            o
        ),
        {}
    );

console.log(obj);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 1

Related Questions