javascript - Konverter objektarray til hash-kart, indeksert etter en attributtverdi til objektet
Brukstilfelle
Brukstilfellet er å konvertere et array av objekter til et hash-kart basert på en streng eller funksjon som gis for å evaluere og bruke som nøkkel i hash-kartet, og verdien som objektet selv. Et vanlig tilfelle for bruk av dette er å konvertere et array av objekter til et hash-kart av objekter.
Kode
Følgende er et lite utdrag i JavaScript for å konvertere et array av objekter til et hash-kart, indeksert etter objektets attributtverdi. Du kan gi en funksjon for å evaluere nøkkelen til hash-kartet dynamisk (kjøretid).
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;
};
Du kan finne hovedpoenget her: Konverterer array av objekter til HashMap.
Svar #1
Dette er ganske trivielt å gjøre med 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' }Merk: Array.prototype.reduce() er IE9+, så hvis du trenger å støtte eldre nettlesere må du polyfille det.
Svar #2
Ved å bruke ES6 Map (ganske godt støttet), kan du prøve dette:
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"}Svar #3
Du kan bruke den nye Object.fromEntries()-metoden.
Eksempel :
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}Svar #4
Bruke 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}
Svar #5
Med lodash kan dette gjøres ved å bruke 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}
Svar #6
🏆 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}), {})
)Svar #7
Ved å bruke spredningsoperatoren:
const result = arr.reduce(
(accumulator, target) => ({ ...accumulator, [target.key]: target.val }),
{});
Demonstrasjon av kodeeksemplet på jsFiddle.
Svar #8
Du kan bruke Array.prototype.reduce() og faktisk JavaScript Map i stedet for bare et JavaScript-objekt.
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);
Hva er forskjellen mellom Map og Object?
Tidligere, før Map ble implementert i JavaScript, har Object blitt brukt som en Map på grunn av deres lignende struktur.
Avhengig av bruksområdet ditt, hvis du trenger å ha ordnede nøkler, trenger å få tilgang til størrelsen på mappen eller har hyppig tillegg og fjerning fra mappen, er en Map å foretrekke.
Sitat fra MDN-dokument:
Objekter ligner på Kart (Maps) ved at begge lar deg sette nøkler til verdier, hente disse verdiene, slette nøkler og sjekke om noe er lagret under en nøkkel. På grunn av dette (og fordi det ikke fantes innebygde alternativer), har objekter historisk blitt brukt som Kart; imidlertid er det viktige forskjeller som gjør at bruk av et Kart kan være å foretrekke i visse tilfeller:
- Nøklene til et Object er Strenger og Symboler, mens de kan være hvilken som helst verdi for et Map, inkludert funksjoner, objekter og alle primitive verdier.
- Nøklene i Map er ordnet, mens nøkler lagt til i objekt ikke er det. Derfor, når man itererer over det, returnerer et Map-objekt nøkler i innsettingsrekkefølge.
- Du kan enkelt få størrelsen på et Map med størrelse-egenskapen, mens antallet egenskaper i et Object må bestemmes manuelt.
- Et kart er iterabelt og kan derfor itereres direkte, mens iterering over et objekt krever at man på en eller annen måte får tak i nøklene og itererer over dem.
- Et objekt har et prototype, så det finnes standardnøkler i kartet som kan kollidere med nøklene dine hvis du ikke er forsiktig. Fra ES5 kan dette omgås ved å bruke map=Object.create(null), men dette gjøres sjelden.
- Et kart kan prestere bedre i scenarier som innebærer hyppig tillegg og fjerning av nøkkelpar.
Svar #9
es2015-versjon:
const myMap = new Map(objArray.map(obj => [ obj.key, obj.val ]));
Svar #10
Det finnes bedre måter å gjøre dette på som forklart av andre innlegg. Men hvis jeg vil holde meg til ren JS og gammeldags måte, så her er det:
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);
