Search code examples
javascriptnode.jsfunctional-programmingmap-function

map function for objects (instead of arrays)


I have an object:

myObject = { 'a': 1, 'b': 2, 'c': 3 }

I am looking for a native method, similar to Array.prototype.map that would be used as follows:

newObject = myObject.map(function (value, label) {
    return value * value;
});

// newObject is now { 'a': 1, 'b': 4, 'c': 9 }

Does JavaScript have such a map function for objects? (I want this for Node.JS, so I don't care about cross-browser issues.)


Solution

  • There is no native map to the Object object, but how about this:

    var myObject = { 'a': 1, 'b': 2, 'c': 3 };
    
    Object.keys(myObject).forEach(function(key, index) {
      myObject[key] *= 2;
    });
    
    console.log(myObject);
    // => { 'a': 2, 'b': 4, 'c': 6 }

    But you could easily iterate over an object using for ... in:

    var myObject = { 'a': 1, 'b': 2, 'c': 3 };
    
    for (var key in myObject) {
      if (myObject.hasOwnProperty(key)) {
        myObject[key] *= 2;
      }
    }
    
    console.log(myObject);
    // { 'a': 2, 'b': 4, 'c': 6 }

    Update

    A lot of people are mentioning that the previous methods do not return a new object, but rather operate on the object itself. For that matter I wanted to add another solution that returns a new object and leaves the original object as it is:

    var myObject = { 'a': 1, 'b': 2, 'c': 3 };
    
    // returns a new object with the values at each key mapped using mapFn(value)
    function objectMap(object, mapFn) {
      return Object.keys(object).reduce(function(result, key) {
        result[key] = mapFn(object[key])
        return result
      }, {})
    }
    
    var newObject = objectMap(myObject, function(value) {
      return value * 2
    })
    
    console.log(newObject);
    // => { 'a': 2, 'b': 4, 'c': 6 }
    
    console.log(myObject);
    // => { 'a': 1, 'b': 2, 'c': 3 }

    Array.prototype.reduce reduces an array to a single value by somewhat merging the previous value with the current. The chain is initialized by an empty object {}. On every iteration a new key of myObject is added with twice the key as the value.

    Update

    With new ES6 features, there is a more elegant way to express objectMap.

    const objectMap = (obj, fn) =>
      Object.fromEntries(
        Object.entries(obj).map(
          ([k, v], i) => [k, fn(v, k, i)]
        )
      )
      
    const myObject = { a: 1, b: 2, c: 3 }
    
    console.log(objectMap(myObject, v => 2 * v))