Convert an array to an array of objects
Asked Answered
D

4

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.

Disqualify answered 27/12, 2013 at 21:4 Comment(5)
you don't need to convert. an array already is an objectRubefaction
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: eloquentjavascript.net/chapter4.html.Rejection
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]]Silage
["fruits":"apple", is not legal. [{"fruits":"apple"}, doesGynandrous
Just a note that you've got the notation wrong in your "first object as" example - objects are wrapped in { }, arrays in [ ]Nerissanerita
S
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 }
]
Silage answered 27/12, 2013 at 21:15 Comment(1)
Upvoted. Using two for loops is the simplest solution, though my approach with map() is more elegant, imo.Goatee
C
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 } 
]
Cermet answered 21/7, 2015 at 10:5 Comment(0)
G
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/

Goatee answered 27/12, 2013 at 21:29 Comment(4)
Definitely more elegant, I agree. Unfortunately, it's 160x slower in Chrome 31.0.1650. (maybe I setup the test wrong? I didn't expect that) Also, map() is essentially an encapsulated iteration, so you are still iterating twice.Silage
@Silage you kinda took advantage of me in that test: 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.Goatee
Sorry about that. It wasn't on purpose :DSilage
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.bl.ocks.org/mbostock/3885211.Disqualify
N
4

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)
Negrophobe answered 4/6, 2020 at 14:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.