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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26264956/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 22:38:37  来源:igfitidea点击:

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

javascriptarrayshashmap

提问by Naveen I

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 value as an object itself. A common case of using this is converting an array of objects into a hash map of objects.

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

Code

代码

The following is a small snippet in JavaScript to convert an array of objects to a hash map, indexed by the attribute value of object. You can provide a function to evaluate the key of hash map dynamically (run time). Hope this helps someone in future.

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

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 hashmap
 * @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;
};

You can find the gist here: Converts Array of Objects to HashMap.

您可以在此处找到要点:将对象数组转换为 HashMap

回答by jmar777

This is fairly trivial to do with Array.prototype.reduce:

这与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' }

Note:Array.prototype.reduce()is IE9+, so if you need to support older browsers you will need to polyfill it.

注意:Array.prototype.reduce()是 IE9+,所以如果你需要支持旧浏览器,你需要对它进行 polyfill。

回答by mateuscb

Using ES6 Map(pretty well supported), you can try this:

使用 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"}

回答by splintor

With lodash, this can be done using keyBy:

使用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}

回答by shuk

Using ES6 spread + Object.assign:

使用 ES6 扩展 + 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}

回答by Pedro Lopes

Using the spread operator:

使用扩展运算符:

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

Demonstration of the code snippet on jsFiddle.

jsFiddle上演示代码片段。

回答by Fabiano Taioli

You can use the new Object.fromEntries()method.

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

Example:

例子:

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}

回答by Jun711

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

您可以使用Array.prototype.reduce()和实际的 JavaScript Map而不是 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.

Map 和 Object 有什么区别?
以前,在 JavaScript 实现 Map 之前,Object 因为它们的结构相似而被用作 Map。
根据您的用例,如果您需要有序的键、需要访问地图的大小或需要频繁地从地图中添加和删除,则最好使用地图。

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:

引自MDN 文档
对象与 Maps 类似,都可以让您将键设置为值、检索这些值、删除键,以及检测某个键是否存储了某些内容。正因为如此(并且因为没有内置的替代品),对象在历史上一直被用作地图;然而,在某些情况下,使用 Map 有一些重要的区别:

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

回答by baryo

es2015 version:

es2015版本:

const myMap = new Map(objArray.map(obj => [ obj.key, obj.val ]));

回答by Peter

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

这就是我在 TypeScript 中所做的我有一个小的 utils 库,我把这样的东西

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'

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

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

回答by Tiago Bértolo

If you want to convert to the new ES6 Mapdo this:

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

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.

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