Thursday, December 15, 2016

Mapping Object Arrays

I've been offline for a little while. I've started a new gig and I've been taking the time to get up to speed on a few things. When a learning curve overlaps holiday festivities and familial responsibilities, other things tend to get pushed aside. Remember, we only have one life to live and doing too much leads to burn-out and a reduced ability to think...and since you're getting paid to think, well, burn-out is your enemy.

Today, I'm going to do a quick post to explain how to do something in a new way. Of course, as you know, there are usually several ways to solve a problem and part of our challenge is selecting the right way for our situation. So, here's the problem...I have an object array but I want to turn that into a hash using JavaScript. I want to use a hash because I definitely don't want to do a for..in loop every time I need to look up a value - those loops are horribly expensive - and I don't really want to do a for loop to look through all the array elements either, because that means I'd either have to write a method (and store it somewhere) to look up the value or I'd have to write an ad hoc for loop, meaning I'm going to end up repeating myself somewhere.

So, how do I fix this?

One solution is to extend the Array object, and then call the method I've used to extend the array. Luckily for us, the Array object already has a native loop that's faster than forEach - reduce. We typically use reduce to do simple things, like generating a cumulative total, but we don't need to - it can go beyond that. Here's the extension...


JavaScript - A transformation method using reduce

Array.prototype.hash = function(key) {   var mapped = { }, prop = this[0][key];   mapped[prop] = this[0];   this.reduce(function(init, current) {      init[current[key]] = current;      return init;   }, mapped);   return mapped; };

The extension method returns an object with the corresponding values mapped to the values contained in the key property in each element.

As an example, if I have an object array like...


JavaScript - The object array to be transformed

var objs = [   {key:'foo', value:'bar'},   {key:'bar', value:'blocked'},   {key:'status', value:'snafu'},   {key:'snafu', value:'fubar'} ];

...and I call the extension function to map the key property...

JavaScript - Calling the hash extension

var hashed = objs.hash('key');

...I get an object back that is...

JSON - The object returned by the hash function

{   "foo": {"key":"foo","value":"bar"},   "bar": {"key":"bar","value":"blocked"},   "status": {"key":"status","value":"snafu"},   "snafu":{"key":"snafu","value":"fubar"} }

Simple, straightforward, quick. Of course our hash extension method could use a for loop - something like this - ...

JavaScript hash function using a for loop

Array.prototype.hash = function(key) {   var mapped = { }, c;   for (c = 0; c < this.length; c += 1) {     mapped[this[c][key]] = this[c];   }   return mapped; };

...and for loops are quick, but most of us know how to use for loops but may not know how to use reduce in a way that's a little less obvious...and looking at things in a new way is one of the easiest ways to expand your thinking.

Happy coding.

No comments:

Post a Comment