Extract attribute of an object from a list of objects in Javascript

I have the following object that I receive from the API:

{
   '2012-12-12': [
       { 'id': 1234,
         'type': 'A' },
       { 'id': 1235,
         'type': 'A' },
       { 'id': 1236,
         'type': 'B' },
    ],
   '2012-12-13': [
       { 'id': 1237,
         'type': 'A' },
       { 'id': 1238,
         'type': 'C' },
       { 'id': 1239,
         'type': 'B' },
    ]
}

      

Then I want to have another variable named types

type Array

that will contain all possible attribute values type

for each of the objects. In this case it will be:

types = ['A', 'B', 'C']

      

I'm trying to do it in a functional way (I'm using underscore.js), but I can't figure out how. Right now I am using

types = [];
_.each(response, function(arr1, key1) {
    _.each(arr1, function(arr2, key2) {
        types.push(arr2.type);
    });
});
types = _.uniq(types);

      

But this is very ugly. Can you help me design a better way to write this code?

Thank!

+3


source to share


2 answers


This should work:

types = _.chain(input) // enable chaining
  .values()            // object to array
  .flatten()           // 2D array to 1D array
  .pluck("type")       // pick one property from each element
  .uniq()              // only the unique values
  .value()             // get an unwrapped array

      

Fiddle: http://jsfiddle.net/NFSfs/

You can of course remove all spaces if you like:

types = _.chain(input).values().flatten().pluck("type").uniq().value()

      



or without chaining:

types = _.uniq(_.pluck(_.flatten(_.values(input)),"type"));

      


anti-aliasing seems to work on objects , although the documentation clearly states it shouldn't . If you want to execute code versus implementation, you can leave the call values

, but I don't recommend doing that. The implementation can change one day, leaving your code mysteriously broken.

+5


source


If you need shorter code, you can flatten the objects into one array and then display that array.

var types = _.unique(_.map(_.flatten(_.toArray(response)), function(arr) {
    return arr.type;
}));

      




Here's another version. Mostly just for the sake of curiosity.

var types = _.unique(_.pluck(_.reduce(response, _.bind(Function.apply, [].concat), []), "type"));

      




Here's another one.

var types = _.unique(_.reduce(response, function(acc, arr) {
    return acc.concat(_.pluck(arr,"type"));
}, []));

      




And further.

var types = _.unique(_.pluck([].concat.apply([], _.toArray(response)), "type"))

      

+1


source







All Articles