15

How I can convert an array to an array of JavaScript objects.

For example I have an array as

data = [
    ["fruits","frozen","fresh","rotten"],
    ["apples",884,494,494],
    ["oranges",4848,494,4949],
    ["kiwi",848,33,33]
]

I want to convert it to a name value pair.

For example, first object in the resulting collection would be

 {"fruits": "apple", "frozen": 884, "fresh": 494, "rotten": 494}

and so on for rest of the data.

Ram
  • 3,092
  • 10
  • 40
  • 56
user3084017
  • 177
  • 1
  • 2
  • 9
  • you don't need to convert. an array already is an object – Sam I am says Reinstate Monica Dec 27 '13 at 21:05
  • 3
    Where exactly are you stuck? Looks like you have to iterate over the first array for the keys and all the others to get the values. Do you know how to iterate over arrays? There are guides which explain that: http://eloquentjavascript.net/chapter4.html. – Felix Kling Dec 27 '13 at 21:05
  • Do you want: `["fruits":"apples","frozen":884,"fresh":494,"rotten":494],["fruits":"oranges","frozen":4848,"fresh":494,"rotten":4949]` or `["fruits":["apples", "oranges"],"frozen":[884, 4848],"fresh":[494,494],"rotten":[494,4949]]` – crush Dec 27 '13 at 21:08
  • 1
    `["fruits":"apple",` is not legal. `[{"fruits":"apple"},` does – Royi Namir Dec 27 '13 at 21:09
  • 1
    Just a note that you've got the notation wrong in your "first object as" example - objects are wrapped in `{` `}`, arrays in `[` `]` – John Carter Dec 27 '13 at 21:10

4 Answers4

10

DEMO

Using your supplied data:

var data = [
    ["fruits","frozen","fresh","rotten"],
    ["apples",884,494,494],
    ["oranges",4848,494,4949],
    ["kiwi",848,33,33]
]

The following function will treat the first element of the array as the keys for the objects properties. It will then loop over the remaining elements, and convert them into an object using these keys. Finally, it will return an array of these new objects.

function convertToArrayOfObjects(data) {
    var keys = data.shift(),
        i = 0, k = 0,
        obj = null,
        output = [];

    for (i = 0; i < data.length; i++) {
        obj = {};

        for (k = 0; k < keys.length; k++) {
            obj[keys[k]] = data[i][k];
        }

        output.push(obj);
    }

    return output;
}

Output

[
    { fruits: 'apples', fresh: 494, frozen: 884, rotten: 494 },
    { fruits: 'oranges', fresh: 494, frozen: 4848, rotten: 4949 },
    { fruits: 'kiwi', fresh: 33, frozen: 848, rotten: 33 }
]
crush
  • 16,713
  • 9
  • 59
  • 100
  • Upvoted. Using two for loops is the simplest solution, though my approach with `map()` is more elegant, imo. – Pavlo Dec 27 '13 at 21:39
8

If you use both map and reduce, the solution becomes very elegant:

var collection = [
    ["fruits","frozen","fresh","rotten"],
    ["apples",884,494,494],
    ["oranges",4848,494,4949],
    ["kiwi",848,33,33]
];

var keys = collection.shift();
collection = collection.map(function (row) {
    return keys.reduce(function (obj, key, i) {
      obj[key] = row[i];
      return obj;
    }, {});
});

Output:

[ 
  { fruits: 'apples', frozen: 884, fresh: 494, rotten: 494 },
  { fruits: 'oranges', frozen: 4848, fresh: 494, rotten: 4949 },
  { fruits: 'kiwi', frozen: 848, fresh: 33, rotten: 33 } 
]
Christian Landgren
  • 13,127
  • 6
  • 35
  • 31
6

One can avoid iterating twice using shift() + map() + forEach():

var data = [
    ["fruits","frozen","fresh","rotten"],
    ["apples",884,494,494],
    ["oranges",4848,494,4949],
    ["kiwi",848,33,33]
];

var collection = data.slice(); // make a copy
var keys = collection.shift();

collection = collection.map(function (e) {
    var obj = {};

    keys.forEach(function (key, i) {
        obj[key] = e[i];
    });

    return obj;
});

Demo: http://jsfiddle.net/d7W76/2/

Pavlo
  • 43,301
  • 14
  • 77
  • 113
  • 3
    Definitely more elegant, I agree. Unfortunately, it's [160x slower in Chrome 31.0.1650](http://jsperf.com/testing-map-foreach-vs-2x-for-statements). (maybe I setup the test wrong? I didn't expect that) Also, `map()` is essentially an encapsulated iteration, so you are still iterating twice. – crush Dec 27 '13 at 21:47
  • @crush you kinda took advantage of me in that test: http://jsperf.com/testing-map-foreach-vs-2x-for-statements/2 But my algorithm is much slower anyway. Obviously there is a room for `map()` optimisation in V8 and other JS engines. – Pavlo Dec 27 '13 at 22:14
  • Sorry about that. It wasn't on purpose :D – crush Dec 27 '13 at 22:14
  • I was trying to make a stacked area chart with the above data.but somehow I am unable to understand how to use the data for stacked bar data.http://bl.ocks.org/mbostock/3885211. – user3084017 Jan 03 '14 at 21:57
3

Destructing:

const data = [
    ["fruits","frozen","fresh","rotten"],
    ["apples",884,494,494],
    ["oranges",4848,494,4949],
    ["kiwi",848,33,33]
]
const titles = data[0]
const obj = data.slice(1).map(([fruits,frozen,fresh,rotten]) => ({ fruits,frozen,fresh,rotten }) )
console.log(obj)
mplungjan
  • 169,008
  • 28
  • 173
  • 236