Convert object array to hash map, indexed by an attribute value of the Object

前端 未结 16 2427
忘掉有多难
忘掉有多难 2020-11-28 01:08

Use Case

The use case is to convert an array of objects into a hash map based on string or function provided to evaluate and use as the key in the hash map and val

相关标签:
16条回答
  • 2020-11-28 01:31

    If you want to convert to the new ES6 Map do this:

    var kvArray = [['key1', 'value1'], ['key2', 'value2']];
    var myMap = new Map(kvArray);
    

    Why should you use this type of Map? Well that is up to you. Take a look at this.

    0 讨论(0)
  • 2020-11-28 01:32

    Using ES6 spread + Object.assign:

    array = [{key: 'a', value: 'b', redundant: 'aaa'}, {key: 'x', value: 'y', redundant: 'zzz'}]
    
    const hash = Object.assign({}, ...array.map(s => ({[s.key]: s.value})));
    
    console.log(hash) // {a: b, x: y}
    
    0 讨论(0)
  • 2020-11-28 01:36

    A small improvement on the reduce usage:

    var arr = [
        { key: 'foo', val: 'bar' },
        { key: 'hello', val: 'world' }
    ];
    
    var result = arr.reduce((map, obj) => ({
        ...map,
        [obj.key] = obj.val
    }), {});
    
    console.log(result);
    // { foo: 'bar', hello: 'world' }
    
    0 讨论(0)
  • 2020-11-28 01:37

    You can use Array.prototype.reduce() and actual JavaScript Map instead just a JavaScript Object.

    let keyValueObjArray = [
      { key: 'key1', val: 'val1' },
      { key: 'key2', val: 'val2' },
      { key: 'key3', val: 'val3' }
    ];
    
    let keyValueMap = keyValueObjArray.reduce((mapAccumulator, obj) => {
      // either one of the following syntax works
      // mapAccumulator[obj.key] = obj.val;
      mapAccumulator.set(obj.key, obj.val);
    
      return mapAccumulator;
    }, new Map());
    
    console.log(keyValueMap);
    console.log(keyValueMap.size);
    

    What is different between Map And Object?
    Previously, before Map was implemented in JavaScript, Object has been used as a Map because of their similar structure.
    Depending on your use case, if u need to need to have ordered keys, need to access the size of the map or have frequent addition and removal from the map, a Map is preferable.

    Quote from MDN document:
    Objects are similar to Maps in that both let you set keys to values, retrieve those values, delete keys, and detect whether something is stored at a key. Because of this (and because there were no built-in alternatives), Objects have been used as Maps historically; however, there are important differences that make using a Map preferable in certain cases:

    • The keys of an Object are Strings and Symbols, whereas they can be any value for a Map, including functions, objects, and any primitive.
    • The keys in Map are ordered while keys added to object are not. Thus, when iterating over it, a Map object returns keys in order of insertion.
    • You can get the size of a Map easily with the size property, while the number of properties in an Object must be determined manually.
    • A Map is an iterable and can thus be directly iterated, whereas iterating over an Object requires obtaining its keys in some fashion and iterating over them.
    • An Object has a prototype, so there are default keys in the map that could collide with your keys if you're not careful. As of ES5 this can be bypassed by using map = Object.create(null), but this is seldom done.
    • A Map may perform better in scenarios involving frequent addition and removal of key pairs.
    0 讨论(0)
  • 2020-11-28 01:37

    This is what I'm doing in TypeScript I have a little utils library where I put things like this

    export const arrayToHash = (array: any[], id: string = 'id') => 
             array.reduce((obj, item) =>  (obj[item[id]] = item , obj), {})
    

    usage:

    const hash = arrayToHash([{id:1,data:'data'},{id:2,data:'data'}])
    

    or if you have a identifier other than 'id'

    const hash = arrayToHash([{key:1,data:'data'},{key:2,data:'data'}], 'key')
    
    0 讨论(0)
  • 2020-11-28 01:43

    There are better ways to do this as explained by other posters. But if I want to stick to pure JS and ol' fashioned way then here it is:

    var arr = [
        { key: 'foo', val: 'bar' },
        { key: 'hello', val: 'world' },
        { key: 'hello', val: 'universe' }
    ];
    
    var map = {};
    for (var i = 0; i < arr.length; i++) {
        var key = arr[i].key;
        var value = arr[i].val;
    
        if (key in map) {
            map[key].push(value);
        } else {
            map[key] = [value];
        }
    }
    
    console.log(map);
    
    0 讨论(0)
提交回复
热议问题