Underscore.js convert object to array

21,594

Solution 1

You're almost there:

var orderedProduction = _.chain(production)
    .groupBy(function (entity) {
        return entity.key[0];
    })
    .map(function (vals, key) {
        return [key, _.pluck(vals, 'value')]
    })
    .object()
    .value();

returns

{ wind: [ 5, 9, 11, 7 ],
  solar: [ 1, 1, 2, 3 ],
  oil: [ 15, 16, 22, 23 ] }

Solution 2

You can simply use the map() function provided in javascript. The _.map() given is for backward compatibility. Anyways, here is the code :

var obj = {};
production.map(function(data) {
    if(data.key[0] in obj) {
        obj[data.key[0]] += data.value;
    } else {
        obj[data.key[0]] = 0;
        obj[data.key[0]] += data.value;
    }
});
console.log(obj);

So what is does is that it loops throught the production array. There, it checks whether the key(for example, 'key' is the key) is in the obj object or not. If it is there then it simply increments its value or else makes a new key and assigns it 0 and then increments it.

Not the most optimized code but it works nicely.

Solution 3

This is probably not the best performing code, but it gets the job done using underscore.

Live Demo

var production = [
    {key: ["wind", "1"], value: 5},
    {key: ["wind", "2"], value: 9},
    {key: ["wind", "3"], value: 11},
    {key: ["wind", "4"], value: 7},
    {key: ["solar", "1"], value: 1},
    {key: ["solar", "2"], value: 1},
    {key: ["solar", "3"], value: 2},
    {key: ["solar", "4"], value: 3},
    {key: ["oil", "1"], value: 15},
    {key: ["oil", "2"], value: 16},
    {key: ["oil", "3"], value: 22},
    {key: ["oil", "4"], value: 23}
];

var orderedProduction =  _.chain(production)
    .groupBy(function (entity) {
        return entity.key[0];
    })
    .map(function(items, key){
        var returnVal = [key]; 
        var total = 0; 
        returnVal.push(_.map(items, function(obj){
            total += obj.value; 
            return obj.value; 
        })); 

        if(total > 10){
            return returnVal; 
        }

    })
    .filter(function(num) {
        return num !== undefined;
    })
    .object()
    .value();

console.log(production);
console.log(orderedProduction);
Share:
21,594
Husman
Author by

Husman

A programmer who enjoys musing at random technology questions. A little strange. A lot of fun.

Updated on September 17, 2020

Comments

  • Husman
    Husman over 3 years

    I'm relatively new to underscore.js and I have an object coming in from a REST service which looks like this (I have typed it out by hand and assigned it to a var here):

    var production = [
        {key: ["wind", "1"], value: 5},
        {key: ["wind", "2"], value: 9},
        {key: ["wind", "3"], value: 11},
        {key: ["wind", "4"], value: 7},
        {key: ["solar", "1"], value: 1},
        {key: ["solar", "2"], value: 1},
        {key: ["solar", "3"], value: 2},
        {key: ["solar", "4"], value: 3},
        {key: ["oil", "1"], value: 15},
        {key: ["oil", "2"], value: 16},
        {key: ["oil", "3"], value: 22},
        {key: ["oil", "4"], value: 23},
    ];
    

    Then further down, I have some code that parses this object and creates arrays for the items like so:

    var orderedProduction = _.chain(production)
          .groupBy(function (entity) {
                return entity.key[0];
          })
          .map(function (values) { 
                return _.map(values, function (entity2) {
                      return entity2.value;
                });
          })
          .value();
    

    This gives the following results:

    orderedProduction  = [
      [5, 9, 11, 7],
      [1, 1, 2, 3],
      [15, 16, 22, 23]
    ]
    

    Which loses the keys (wind/solar/oil). And is used to draw a graph. I'm further able to check if some of these arrays meet a certain threshold like so:

    var threshold = _.map(orderedProduction  , function(arr) {
        return _.max(arr) > 10;
    });
    

    My requirements have now changed and I now need to filter out these arrays by its total sum, while retaining the key.

    What I would like to end up with an object like so:

    orderedProduction  = {
          "wind": [5, 9, 11, 7],
          "solar": [1, 1, 2, 3],
          "oil": [15, 16, 22, 23]
        }
    

    It would be great if the fix included a way to sum up the values of the array and remove those that do not total up to a certain amount. (i.e. exclude solar, if it does not add up to 10).

    Here is a jsfiddle I created to test this all out on: http://jsfiddle.net/2mfjw3jk/


    UPDATE: The solution I settled for was this:

    var orderedProduction = _.chain(production)
        .groupBy(function (entity) {
            return entity.key[0];
        })
        .map(function (vals, key) {
            return [key, _.pluck(vals, 'value')]
        })
        .filter(function(arr) {
            var sum = 0;
            _.each(arr[1], function(num){
                sum += num;
            })
            return sum > 10;
        })
        .object()
        .value();
    

    It also filters the values by a predetermined threshold (10 in this case).