web-dev-qa-db-fra.com

Convertit un tableau d'objet en hash map, indexé par une valeur d'attribut de l'objet

Cas d'utilisation

Le cas d'utilisation consiste à convertir un tableau d'objets en une carte de hachage basée sur une chaîne ou une fonction fournie pour évaluation et à utiliser comme clé dans hashmap et la valeur en tant qu'objet lui-même. Le cas courant d'utilisation de ceci est la conversion d'un tableau d'objets en une carte de hachage d'objets.

Code

Voici un petit extrait de code javascript permettant de convertir un tableau d'objets en hash map, indexés par la valeur d'attribut de l'objet. Vous pouvez fournir une fonction pour évaluer la clé de la carte de hachage de manière dynamique (exécution). J'espère que cela aidera tout le monde à l'avenir.

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

Vous pouvez trouver le résumé ici: https://Gist.github.com/naveen-ithappu/c7cd5026f6002131c1fa

197
Naveen I

C’est assez simple à faire avec 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' }
_

Remarque: Array.prototype.reduce() est IE9 +. Par conséquent, si vous devez prendre en charge des navigateurs plus anciens, vous devrez le polyfiller.

342
jmar777

En utilisant ES6 Map ( assez bien supporté ), vous pouvez essayer ceci:

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

Avec lodash , vous pouvez utiliser 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}
33
splintor

En utilisant l'opérateur de propagation:

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

Démonstration de l'extrait de code sur jsFiddle .

20
Pedro Lopes

Utilisation de 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}
17
shukar

Vous pouvez utiliser Array.prototype.reduce () et le code JavaScript actuel Map au lieu de JavaScript uniquement. Objet .

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);

Quelle est la différence entre Map And Object?
Auparavant, avant que Map ne soit implémenté en JavaScript, Object était utilisé en tant que Map en raison de sa structure similaire.
En fonction de votre cas d'utilisation, si vous devez avoir besoin de clés commandées, si vous devez accéder à la taille de la carte ou si des ajouts et des retraits sont fréquents, une carte est préférable.

Citation de document MDN :
Les objets sont similaires aux cartes en ce qu’ils vous permettent de définir des valeurs pour les clés, de récupérer ces valeurs, de supprimer des clés et de détecter si un élément est stocké dans une clé. Pour cette raison (et parce qu'il n'y avait pas d'alternative intégrée), les objets ont été utilisés historiquement comme cartes; Cependant, il existe des différences importantes qui rendent l'utilisation d'une carte préférable dans certains cas:

  • Les clés d'un objet sont des chaînes et des symboles, alors qu'elles peuvent être n'importe quelle valeur pour une carte, y compris les fonctions, les objets et toute primitive.
  • Les clés dans Map sont ordonnées alors que les clés ajoutées à l'objet ne le sont pas. Ainsi, lors de son itération, un objet Map renvoie les clés dans l'ordre d'insertion.
  • Vous pouvez facilement obtenir la taille d'une carte avec la propriété size, tandis que le nombre de propriétés dans un objet doit être déterminé manuellement.
  • Une carte est un itératif et peut donc être directement itérée, alors que itérer sur un objet nécessite d’obtenir ses clés d’une certaine manière et de les itérer.
  • Un objet a un prototype, il y a donc des clés par défaut dans la carte qui pourraient entrer en collision avec vos clés si vous ne faites pas attention. À partir de ES5, cela peut être contourné en utilisant map = Object.create (null), mais cela est rarement fait.
  • Une carte peut mieux fonctionner dans des scénarios impliquant l'ajout et le retrait fréquents de paires de clés.
12
Jun711

version es2015:

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

C'est ce que je fais dans TypeScript. J'ai une petite bibliothèque utils dans laquelle je mets des choses comme celle-ci.

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

ou si vous avez un identifiant autre que 'id'

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

Utiliser du Javascript simple

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
2
Partha Roy

Il existe de meilleures façons de le faire, comme l'expliquent d'autres affiches. Mais si je veux rester fidèle à JS et à l’ancienne façon de le faire, la voici:

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);
1
rhel.user

Si vous souhaitez convertir le nouvel ES6 Carte procédez comme suit:

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

Pourquoi devriez-vous utiliser ce type de carte? C'est à vous de décider. Jetez un oeil à this .

1
Tiago Bértolo

essayer

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) );
1

Vous pouvez utiliser la nouvelle méthode 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}
1
Fabiano Taioli

Une petite amélioration sur l'utilisation de 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' }
1
Mor Shemesh

Voici un petit extrait que j'ai créé en javascript pour convertir un tableau d'objets en hash map, indexé par la valeur d'attribut de l'objet. Vous pouvez fournir une fonction pour évaluer la clé de la carte de hachage de manière dynamique (exécution).

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

Vous pouvez trouver le résumé ici: https://Gist.github.com/naveen-ithappu/c7cd5026f6002131c1fa

0
Naveen I