15

Is there an easy/clean way using Underscore to turn this

[ { id: 'medium', votes: 7 },
  { id: 'low',    votes: 9 },
  { id: 'high',   votes: 5 } ]

Into

 { 'low'    : 9,
   'medium' : 7,
   'high'   : 5 }

8 Answers 8

43

You might consider _.indexBy(...)

var data = [{
    id: 1,
    name: 'Jon Doe',
    birthdate: '1/1/1991',
    height: '5 11'
}, {
    id: 2,
    name: 'Jane Smith',
    birthdate: '1/1/1981',
    height: '5 6'
}, {
    id: 3,
    name: 'Rockin Joe',
    birthdate: '4/4/1994',
    height: '6 1'
}, {
    id: 4,
    name: 'Jane Blane',
    birthdate: '1/1/1971',
    height: '5 9'
}, ];

var transformed = _.indexBy(data, 'id');

Here is a fiddle: https://jsfiddle.net/4vyLtcrf/3/

Update: In Lodash 4.0.1 the method _.indexBy has been renamed to _.keyBy

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

2 Comments

+1 for readability. Worth noting that the id property will still be present in the resulting objects, but that should be okay in most cases (and easy to post-exclude in others).
A similar solution for those looking to have each key in the final object as an array of items with that key (as opposed to a single item), there's also _.groupBy()
17
var data = [ { id: 'medium', votes: 7 },
  { id: 'low',    votes: 9 },
  { id: 'high',   votes: 5 } ];

You can do this with _.map, _.values and _.object, like this

console.log(_.object(_.map(data, _.values)));
# { medium: 7, low: 9, high: 5 }

Explanation

We use the map function to apply the values function (which gets all the values of a given object) over all the elements of data, which would give

# [ [ 'medium', 7 ], [ 'low', 9 ], [ 'high', 5 ] ]

Then we use object function to transform this into an object.

7 Comments

An interesting answer, but perhaps you could clarify what data is firstly, eg data = x;
I used Krasimir's answer, but you answered the question using underscore and there is more to learn for anyone interested in that sort of thing.
@dewd Please check the definition of data. There was a newline. I just removed it now.
How can you be sure that _.values({id: 'medium', votes: 7}) returns ['medium', 7] and not [7, 'medium']?
this solution is unreliable, relying on ordering of properties in your objects
|
8

Here is with vanilla js:

var result = {};
[ { id: 'medium', votes: 7 },
  { id: 'low',    votes: 9 },
  { id: 'high',   votes: 5 } ].forEach(function(obj) {
    result[obj.id] = obj.votes;
});
console.log(result);

Comments

2

simpler with me: each:

   var t = {};
   _.each(x, function(e){
     t[e.id] = e.votes;
   });
//--> {medium: 7, low: 9, high: 5}

Comments

1

The most powerfull method of underscore is reduce. You can do almost anything with it. And the bigger benefit is you iterate over the collection only ONCE!

var array = [ 
    { id: 'medium', votes: 7 },
    { id: 'low',    votes: 9 },
    { id: 'high',   votes: 5 } 
];
var object = _.reduce(array, function(_object, item) { 
    _object[item.id] = item.votes; 
    return _object; 
}, {});

After it runs, object will be:

{
  medium:7,
  low:9,
  high:5
}

3 Comments

It's an anti-pattern to dynamically add new properties to an object in JavaScript. richardartoul.github.io/jekyll/update/2015/04/26/…
Got it! That said @morio, what is your suggested solution?
Hm, you got me. Now I think about it, I don't know if there a way to avoid this. I guess libraries like Lodash are doing the same thing internally.
0

Use indexBy

_.indexBy([ 
   { id: 'medium', votes: 7 },
   { id: 'low',    votes: 9 },
   { id: 'high',   votes: 5 } 
 ], 'id');

Comments

0

I know this is an old post, but you could use _.reduce to do the transform in a clean way

var data = [
    { id: 'medium', votes: 7 },
    { id: 'low',    votes: 9 },
    { id: 'high',   votes: 5 }
]

var output = _.reduce(data, function(memo, entry) {
    memo[entry.id] = entry.votes;
    return memo;
}, {});

console.log(output);

Comments

0

You can do this with native JS Array.reduce

const myArray = [ { id: 'medium', votes: 7 },
{ id: 'low',    votes: 9 },
{ id: 'high',   votes: 5 } ]

const myObject = myArray.reduce((obj, item)=>{
  o[item.id] = item.votes
  return o
}, {})

for more details, take a look at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.