Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

The use case is to convert an array of objects into a hash map where one property is the key and the other property is the value. Common case of using this is converting a "link" object in a hypermedia response into a hash map of links.

jsfiddle

function toHashMap(data, name, value) {
    return _.zipObject(_.pluck(data, name),
                       _.pluck(data, value));
}

function toMap(data, name, value) {
    return _.reduce(data, function(acc, item) {
        acc[item[name]] = item[value];
        return acc;
    }, {});
}

var data = [
    { rel: 'link1', href: 'url1'},
    { rel: 'link2', href: 'url2'},
    { rel: 'link3', href: 'url3'},
    { rel: 'link4', href: 'url4'},
];

console.log(toHashMap(data, 'rel', 'href'));

console.log(toMap(data, 'rel', 'href'));

toHashMap appears much more readable, but less efficient. toMap seems to have the best efficiency at the expense of readability.

Is there a more elegant solution - i.e. both readable and efficient? I suspect that Lodash might have a function to do this already, but I haven't found anything like this after looking at the API documentation.

share|improve this question

2 Answers 2

up vote 23 down vote accepted

I think you are looking for _.indexBY

_.indexBy(data, 'rel');
share|improve this answer
    
I don't understand why is this the accepted answer since it doesn't give the same result as the exposed functions –  Pau Fracés Feb 17 at 15:53
    
@PauFracés See below for revised solution. –  Pete Mar 13 at 21:14

Revised Solution

As per Pau Fracés comment above, here is the complete solution. The solution given by John Anderson would index all objects by the key. However, this would not create a key-value pair map.

To complete the solution of generating a full hash map, the values must be mapped to the key. Using the transform function, the values can be extracted from the objects and mapped back to the key or in this case rel.

Pseudo Code

  1. Index all objects by the chosen key.
  2. Map all values to the key.

Code

Below is the complete code with logging enabled. For a non-logging version, remove all lines with the tap function.

var data = [{ rel: 'link1', href: 'url1' }, 
            { rel: 'link2', href: 'url2' }, 
            { rel: 'link3', href: 'url3' },
            { rel: 'link4', href: 'url4' }];

function log(value) {
  document.getElementById("output").innerHTML += JSON.stringify(value, null, 2) + "\n"
}

var hashmap = _.chain(data)
  .indexBy('rel')

  .tap(log) // Line used just for logging

  .mapValues('href')

  .tap(log)
  
  .value();
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.5.0/lodash.min.js"></script>
<pre id="output"></pre>

share|improve this answer
1  
Nice solution! Personally I would go for mapValues instead of transform. With transform you're updating state outside the closure (it is a side-effecting function), whereas with mapValues you are not. –  Martijn Jul 7 at 9:14
1  
@Martijn Oh great suggestion! Makes for a much cleaner solution IMHO. I've updated the solution with your suggestion. Thanks! –  Pete Jul 10 at 20:21

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.