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

IT技术 javascript arrays hashmap
2021-02-02 20:07:47

用例

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

代码

以下是 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;
};

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

6个回答

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

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

@Mtz 足够公平。
2021-03-22 20:07:47
恕我直言,这不是我们所要求的。对于所示的阵列正确的结果将是:{ "foo": {key: 'foo', val: 'bar'}, "hello": {key: 'hello', val: 'world'} }请注意,应完整保留每个原始元素或者使用Q的数据:{"345": {id:345, name:"kumar"}, ...}修复:将代码更改为map[obj.key] = obj;
2021-03-30 20:07:47
@Mtz 对于 ES6 单线粉丝,mateuscb 下面的回复更小更干净: result = new Map(arr.map(obj => [obj.key, obj.val]));最重要的是,它非常清楚地表明正在返回地图。
2021-04-03 20:07:47
@RyanShillington 我们在这里是一个答案的上下文,这是Array.prototype.reduce由 jmar777 提出的。Map确实更短,但这是另一回事。我是按照原意来的。请记住,这不是论坛,您可能想阅读有关 SO Q/A 结构的更多信息。
2021-04-06 20:07:47
result = arr.reduce((map, obj) => (map[obj.key] = obj.val, map), {}); 对于 ES6 单线风扇 :D
2021-04-07 20:07:47

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

另一个typescript版本: var result = new Map<string, string>(arr.map(i => [i.key, i.val]));
2021-03-28 20:07:47
PSresult不是 OP 要求的哈希。
2021-04-03 20:07:47
当我在 Chrome v71 中运行这段代码时,我仍然得到一个数组: Result is: [["foo","bar"],["hello","world"]]
2021-04-06 20:07:47
同样重要的是要注意,要从 a 中获取某些东西,Map您需要使用result.get(keyName)而不是仅使用result[keyName]. 另请注意,任何对象都可以用作键,而不仅仅是字符串。
2021-04-09 20:07:47
另一个TypeScript版本看起来像这样:var result = new Map(arr.map(i => [i.key, i.val] as [string, string]));有些人可能会觉得更容易理解。as [string, string]添加了注释类型转换。
2021-04-12 20:07:47

您可以使用新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}

这比最佳答案更具可读性;但是,它会迭代数组两次(一次用于map调用,一次用于Object.fromEntries调用)。
2021-03-14 20:07:47
@knguyen 是的,我猜是真的。但在大多数情况下,我想额外的循环无关紧要
2021-03-15 20:07:47

使用 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}
const hash = Object.assign({}, ...(<{}>array.map(s => ({[s.key]: s.value})))); 必须进行此更改才能使用typescript。
2021-03-27 20:07:47
完美,正是我所需要的 ;)
2021-04-08 20:07:47
需要注意的是,此方法不会产生 Map 而是产生一个对象
2021-04-09 20:07:47

使用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}
那不是哈希图
2021-04-09 20:07:47