2

So here is the deal. I have an array that contains a bunch of objects that look something like this:

[{
  "this": 5,
  "that": 300,
  "those": 15
},
{
  "this": 6,
  "that": 301,
  "those": 16
},
{
  "this": 7,
  "that: 302,
  "those": 17
}]

What I want, is an object, that looks like this:

{
  "this": [5, 6, 7],
  "that": [300, 301, 302],
  "those": [15, 16, 17]

}

I don't really know what to call this and by what I searched for, I couldn't find anything similar that would help me.

2
  • I refer to this as transposing an array from row/column to column/row. Commented Feb 4, 2014 at 14:03
  • Here is a jsperf for the two suggested answers. The double for loops are faster in Chrome. Commented Feb 4, 2014 at 14:15

3 Answers 3

2

Try this:

var a = [{
    "this": 5,
    "that": 300,
    "those": 15
},{
    "this": 6,
    "that": 301,
    "those": 16
},{
    "this": 7,
    "that": 302,
    "those": 17
}];

a = a.reduce(
    function(obj, item){             // Map the item to the object.
        obj.this.push(item.this);
        obj.that.push(item.that);
        obj.those.push(item.those);
        return obj;
    },
    {"this":[],"that":[],"those":[]} // Default (empty) object.
);

This uses Array.prototype.reduce().

Sign up to request clarification or add additional context in comments.

1 Comment

You forgot to assign a the reference to the new array. Could assign it to a new variable ofc.
1

For older browsers (i.e. IE8), reduce is not available. If you still want to support these, you can try:

var arr = [{
    "this": 5,
        "that": 300,
        "those": 15
}, {
    "this": 6,
        "that": 301,
        "those": 16
}, {
    "this": 7,
        "that": 302,
        "those": 17
}];

var result = {};
for (var i = 0; i < arr.length; i++) {
    for (var x in arr[i]) {
        if (!result[x]) {
            result[x] = [];
        }
        result[x].push(arr[i][x]);
    }
}
console.log(result);

EDIT: This will also allow modification of the source array without changing the converting code.

3 Comments

Thanks. :) I made one too, but forgot to save it.
Also added a jsperf of the two suggested answers.
This is excellent! I chose this one because it works everywhere without any special needs.
0

Fancy reduce + concat variation

[{"this": 5, "that": 300, "those": 15}, {"this": 6, "that": 301, "those": 16 }, {"this": 7, "that": 302, "those": 17}]

.reduce(function(prev, curr) {
    return {
        "this":  [].concat(prev["this"], [curr["this"]]),
        "that":  [].concat(prev["that"], [curr["that"]]),
        "those": [].concat(prev["those"], [curr["those"]]),
    };
})

Result:

{"this":[5,6,7],"that":[300,301,302],"those":[15,16,17]}

Test in in console yourself.

By using concat we don't have to pass empty {"this":[],"that":[],"those":[]} initial value.

Version #2. Universal code

[{"this": 5, "that": 300, "those": 15}, {"this": 6, "that": 301, "those": 16 }, {"this": 7, "that": 302, "those": 17}]

.reduce(function(prev, curr) {
    for (var key in prev) {
        prev[key] = [].concat(prev[key], curr[key])
    }
    return prev;
})

As you can see this version doesn't make any assumptions about key names.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.