将对象数组转换为哈希映射,由Object的属性值索引

Nav*_*n I 223 javascript arrays hashmap

用例

用例是基于提供的字符串或函数将对象数组转换为哈希映射,以评估和使用hashmap中的键作为对象本身的值.使用它的常见情况是将对象数组转换为对象的哈希映射.

以下是javascript中的小片段,用于将对象数组转换为哈希映射,由对象的属性值索引.您可以提供一个动态(运行时)评估哈希映射键的函数.希望这有助于将来的任何人.

function isFunction(func){
    return Object.prototype.toString.call(func) === '[object Function]';
}

/**
 * This function converts an array to hash map
 * @param {String | function} key describes the key to be evaluated in each object to use as key for hasmap
 * @returns Object
 * @Example 
 *      [{id:123, name:'naveen'}, {id:345, name:"kumar"}].toHashMap("id")
 *      Returns :- Object {123: Object, 345: Object}
 *
 *      [{id:123, name:'naveen'}, {id:345, name:"kumar"}].toHashMap(function(obj){return obj.id+1})
 *      Returns :- Object {124: Object, 346: Object}
 */
Array.prototype.toHashMap = function(key){
    var _hashMap = {}, getKey = isFunction(key)?key: function(_obj){return _obj[key];};
    this.forEach(function (obj){
        _hashMap[getKey(obj)] = obj;
    });
    return _hashMap;
};
Run Code Online (Sandbox Code Playgroud)

你可以在这里找到要点:https://gist.github.com/naveen-ithappu/c7cd5026f6002131c1fa

jma*_*777 371

这很简单Array.prototype.reduce:

var arr = [
    { key: 'foo', val: 'bar' },
    { key: 'hello', val: 'world' }
];

var result = arr.reduce(function(map, obj) {
    map[obj.key] = obj.val;
    return map;
}, {});

console.log(result);
// { foo:'bar', hello:'world' }
Run Code Online (Sandbox Code Playgroud)

注意: Array.prototype.reduce()是IE9 +,因此如果您需要支持旧版浏览器,则需要对其进行填充.

  • `result = arr.reduce((map,obj)=>(map [obj.key] = obj.val,map),{});`对于ES6单线球迷:D (29认同)
  • @Mtz对于ES6单行粉丝,下面的mateuscb响应更小更清晰:`result = new Map(arr.map(obj => [obj.key,obj.val]));`.最重要的是,它可以非常清楚地返回地图. (16认同)
  • 恕我直言,这不是我们所要求的。显示的数组的正确结果是:`{ "foo": {key: 'foo', val: 'bar'}, "hello": {key: 'hello', val: 'world'} }`。请注意,每个原始元素*应完整保留*。或者使用 Q 的数据:`{"345": {id:345, name:"kumar"}, ...}`。修复:将代码更改为“map[obj.key] = obj;” (5认同)
  • @RyanShillington我们处于答案的上下文中,即jmar777提出的“ Array.prototype.reduce”。“地图”确实较短,但这是另一回事。我符合最初的意图。请记住,这不是一个论坛,您可能想阅读有关SO Q / A结构的更多信息。 (2认同)
  • @Mtz公平。 (2认同)

mat*_*scb 251

使用ES6 Map(非常好支持),你可以试试这个:

var arr = [
    { key: 'foo', val: 'bar' },
    { key: 'hello', val: 'world' }
];

var result = new Map(arr.map(i => [i.key, i.val]));

// When using TypeScript, need to specify type:
// var result = arr.map((i): [string, string] => [i.key, i.val])

// Unfortunately maps don't stringify well.  This is the contents in array form.
console.log("Result is: " + JSON.stringify([...result])); 
// Map {"foo" => "bar", "hello" => "world"}
Run Code Online (Sandbox Code Playgroud)

  • 同样重要的是要注意,要从 `Map` 中得到一些东西,你需要使用 `result.get(keyName)` 而不是 `result[keyName]`。另请注意,任何对象都可以用作键,而不仅仅是字符串。 (9认同)
  • 另一种** TypeScript **版本将如下所示:`var result = new Map(arr.map(i => [i.key,i.val] as [string,string]));`了解。注意添加了“ as [string,string]”类型强制转换。 (3认同)

Fab*_*oli 63

您可以使用新Object.fromEntries()方法。

例子:

const array = [
   {key: 'a', value: 'b', redundant: 'aaa'},
   {key: 'x', value: 'y', redundant: 'zzz'}
]

const hash = Object.fromEntries(
   array.map(e => [e.key, e.value])
)

console.log(hash) // {a: b, x: y}
Run Code Online (Sandbox Code Playgroud)

  • 这比最上面的答案更具可读性;但是,它将迭代该数组两次(一次用于“map”调用,一次用于“Object.fromEntries”调用)。 (2认同)

spl*_*tor 35

使用lodash,可以使用keyBy完成:

var arr = [
    { key: 'foo', val: 'bar' },
    { key: 'hello', val: 'world' }
];

var result = _.keyBy(arr, o => o.key);

console.log(result);
// Object {foo: Object, hello: Object}
Run Code Online (Sandbox Code Playgroud)

  • 这不是一个哈希图 (3认同)

Jas*_*ing 29

特西斯特

list.reduce((obj, item) => ({...obj, [item.name]: item.value}), {})
Run Code Online (Sandbox Code Playgroud)

list.reduce((obj, item) => ({...obj, [item.name]: item.value}), {})
Run Code Online (Sandbox Code Playgroud)


shu*_*kar 25

使用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}
Run Code Online (Sandbox Code Playgroud)

  • 完美,正是我所需要的;) (2认同)
  • `const hash = Object.assign({}, ...(<{}>array.map(s => ({[s.key]: s.value}))));` 必须进行此更改使用打字稿。 (2认同)
  • 重要的是要注意,此方法不会生成 Map 而是对象 (2认同)

Ped*_*pes 23

使用传播运算符:

const result = arr.reduce(
    (accumulator, target) => ({ ...accumulator, [target.key]: target.val }),
    {});
Run Code Online (Sandbox Code Playgroud)

演示jsFiddle上的代码片段.

  • 因为这个我就在这里!扩散运算符如何再次执行常规旧方法只需分配新密钥并返回累加器?因为它每次创建一个新的副本,然后传播将*表现不佳*! (7认同)
  • 现在你在每次迭代中传播。在减速器中变异应该是安全的。``` const result = arr.reduce( (accumulator, target) => {accumulator[target.key]: target.val; returnaccumulator }, {}); ```` (3认同)

Jun*_*711 13

您可以使用Array.prototype.reduce()和实际的JavaScript Map而不是JavaScript 对象.

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);
Run Code Online (Sandbox Code Playgroud)

地图和对象有什么不同?
以前,在使用JavaScript实现Map之前,Object已被用作Map,因为它们具有相似的结构.
根据您的使用情况,如果您需要拥有订购的密钥,需要访问地图的大小或经常添加和删除地图,最好使用地图.

MDN文档引用:
对象类似于Maps,它们都允许您将键设置为值,检索这些值,删除键,以及检测某些键是否存储在键中.正因为如此(并且因为没有内置替代品),所以对象在历史上被用作地图; 但是,在某些情况下,使用Map更为重要:

  • Object的键是字符串和符号,而它们可以是Map的任何值,包括函数,对象和任何基元.
  • Map中的键是按顺序排列的,而添加到对象的键则不是.因此,当迭代它时,Map对象按插入顺序返回键.
  • 您可以使用size属性轻松获取Map的大小,而Object中的属性数必须手动确定.
  • Map是可迭代的,因此可以直接迭代,而迭代Object需要以某种方式获取其键并迭代它们.
  • 一个对象有一个原型,所以如果你不小心,地图中的默认键可能会与你的键发生碰撞.从ES5开始,这可以通过使用map = Object.create(null)来绕过,但很少这样做.
  • 在涉及频繁添加和删除密钥对的情况下,Map可能表现更好.


小智 9

es2015版本:

const myMap = new Map(objArray.map(obj => [ obj.key, obj.val ]));
Run Code Online (Sandbox Code Playgroud)


rhe*_*ser 9

正如其他海报所解释的那样,有更好的方法可以做到这一点。但如果我想坚持纯 JS 和老式的方式,那么这里是:

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);
Run Code Online (Sandbox Code Playgroud)


Tia*_*olo 6

如果要转换为新的 ES6 Map,请执行以下操作:

var kvArray = [['key1', 'value1'], ['key2', 'value2']];
var myMap = new Map(kvArray);
Run Code Online (Sandbox Code Playgroud)

为什么要使用这种类型的 Map?好吧,这取决于你。看看这个


Pet*_*ter 5

这就是我在 TypeScript 中所做的我有一个小工具库,我把这样的东西放在里面

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

用法:

const hash = arrayToHash([{id:1,data:'data'},{id:2,data:'data'}])
Run Code Online (Sandbox Code Playgroud)

或者如果您有除“id”以外的标识符

const hash = arrayToHash([{key:1,data:'data'},{key:2,data:'data'}], 'key')
Run Code Online (Sandbox Code Playgroud)


Nav*_*n I -2

以下是我在 javascript 中创建的小片段,用于将对象数组转换为哈希映射,并按对象的属性值进行索引。您可以提供一个函数来动态评估哈希映射的键(运行时)。

function isFunction(func){
    return Object.prototype.toString.call(func) === '[object Function]';
}

/**
 * This function converts an array to hash map
 * @param {String | function} key describes the key to be evaluated in each object to use as key for hasmap
 * @returns Object
 * @Example 
 *      [{id:123, name:'naveen'}, {id:345, name:"kumar"}].toHashMap("id")
        Returns :- Object {123: Object, 345: Object}

        [{id:123, name:'naveen'}, {id:345, name:"kumar"}].toHashMap(function(obj){return obj.id+1})
        Returns :- Object {124: Object, 346: Object}
 */
Array.prototype.toHashMap = function(key){
    var _hashMap = {}, getKey = isFunction(key)?key: function(_obj){return _obj[key];};
    this.forEach(function (obj){
        _hashMap[getKey(obj)] = obj;
    });
    return _hashMap;
};
Run Code Online (Sandbox Code Playgroud)

您可以在这里找到要点:https://gist.github.com/naveen-ithappu/c7cd5026f6002131c1fa

  • 拜托,拜托,请不要推荐扩展`Array.prototype`! (16认同)