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

用例

这个用例是根据提供的字符串或函数将对象数组转换为哈希映射,并将其作为哈希映射中的键来计算和使用,并将值作为对象本身。使用这种方法的常见情况是将对象数组转换为对象的哈希映射。

代码

下面是一个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

550776 次浏览

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

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

这对于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+,所以如果你需要支持旧的浏览器,你需要对它进行填充。

使用ES6 地图 (很好的支持),你可以尝试这样做:

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

对于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}

使用简单的Javascript

var createMapFromList = function(objectList, property) {
var objMap = {};
objectList.forEach(function(obj) {
objMap[obj[property]] = obj;
});
return objMap;
};
// objectList - the array  ;  property - property as the key

es2015版本:

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

使用展开运算符:

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

jsFiddle上的代码片段演示。

正如其他帖子解释的那样,有更好的方法来做到这一点。但如果我想坚持纯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);

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

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

用法:

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

或者如果你有一个id以外的标识符

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

你可以使用Array.prototype.reduce ()和实际的JavaScript <强> < /地图强大>来代替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);
Map和Object之间有什么不同?< br > 以前,在Map在JavaScript中实现之前,Object一直被用作Map,因为它们的结构相似 根据你的用例,如果你需要有有序的键,需要访问映射的大小,或者需要频繁地从映射中添加和删除,map是更可取的。< / p >

引用自MDN文档:
对象与map类似,它们都允许您将键设置为值、检索这些值、删除键以及检测是否在键处存储了某些内容。正因为如此(也因为没有内置的替代品),对象在历史上一直被用作地图;然而,在某些情况下使用Map更可取:

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

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

reduce用法的一个小改进:

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

如果你想转换为新的ES6 地图,这样做:

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

为什么要使用这种类型的地图?这取决于你。看看

试一试

let toHashMap = (a,f) => a.reduce((a,c)=> (a[f(c)]=c,a),{});

let arr=[
{id:123, name:'naveen'},
{id:345, name:"kumar"}
];


let fkey = o => o.id; // function changing object to string (key)


let toHashMap = (a,f) => a.reduce((a,c)=> (a[f(c)]=c,a),{});


console.log( toHashMap(arr,fkey) );


// Adding to prototype is NOT recommented:
//
// Array.prototype.toHashMap = function(f) { return toHashMap(this,f) };
// console.log( arr.toHashMap(fkey) );

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

lodash:

const items = [
{ key: 'foo', value: 'bar' },
{ key: 'hello', value: 'world' }
];


const map = _.fromPairs(items.map(item => [item.key, item.val]));


// OR: if you want to index the whole item by key:
// const map = _.fromPairs(items.map(item => [item.key, item]));

lodash fromPairs函数让我想起了Python中的zip函数

链接到lodash

简化版似乎不起作用。我跟随。

   let map = {};
items.forEach(v=>{
map [v.xxx] = v;
});

像这样映射数组:

const items = [
{ key: 'foo', value: 'bar' },
{ key: 'hello', value: 'world' }
];


let [k,v] = items.map(item => [item.key, item.value])
console.log([k,v])


//Output: [ [ 'foo', 'bar' ], [ 'hello', 'world' ] ]

🏆Tersiest

list.reduce((obj, item) => ({...obj, [item.name]: item.value}), {})

const list = [
{ name: 'abc', value: 123 },
{ name: 'xyz', value: 789 },
{ name: 'she', value: 'her' },
{ name: 'he', value: 'him'}
]
  

console.log(
list.reduce((obj, item) => ({...obj, [item.name]: item.value}), {})
)

对我来说,我不喜欢使用任何mapreduce,只坚持使用简单的for循环。

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


const hash = {};


for (const item of array) {
hash[item.key] = item;
}


console.log(hash);

我会在TypeScript中说得更清楚,以防有人感兴趣。

interface Person {
id: number;
name: string;
}
type Result = Map<number, string>


const input: Array<Person> = [
{
id: 123,
name: "naveen"
},
{
id: 345,
name: "kumar"
},
];
const convertedToMap: Result = input.reduce(
(map: Result, person: Person) => {
map.set(person.id, person.name);
return map;
},
new Map()
);