web-dev-qa-db-fra.com

javascript | Regroupement d'objets

J'ai un objet. Il ressemble à ci-dessous:

[
  {
    "name":"Display",
    "group":"Technical detals",
    "id":"60",
    "value":"4"
  },
  {
    "name":"Manufacturer",
    "group":"Manufacturer",
    "id":"58",
    "value":"Apple"
  },
  {
    "name":"OS",
    "group":"Technical detals",
    "id":"37",
    "value":"Apple iOS"
  }
]

Je voudrais regrouper ces données par champ de groupe et obtenir cet objet:

var obj = {
    0 = [
    {
       'group'   = 'Technical detals',
       'name'    = 'Display',
       'id'      = '60',
       'value'   = '4'
    },
    {
       'group'   = 'Technical detals',
       'name'    = 'OS',
       'id'      = '37',
       'value'   = 'Apple iOS'
    }],
    1   = [
    {
       'group'   = 'Manufacturer',
       'name'    = 'Manufacturer',
       'id'      = '58',
       'value'   = 'Apple'
    }]
}

Comment regrouper mon premier objet?

15
XTRUST.ORG

Essayez avec quelque chose comme ça:

function groupBy(collection, property) {
    var i = 0, val, index,
        values = [], result = [];
    for (; i < collection.length; i++) {
        val = collection[i][property];
        index = values.indexOf(val);
        if (index > -1)
            result[index].Push(collection[i]);
        else {
            values.Push(val);
            result.Push([collection[i]]);
        }
    }
    return result;
}

var obj = groupBy(list, "group");

Garde en tête que Array.prototype.indexOf n'est pas défini dans IE8 et les versions antérieures, mais il existe des polyfills communs pour cela.

21
MaxArt

Si vous utilisez underscore.js dans votre application, vous pouvez simplement faire ce qui suit:

var groups = _.groupBy(data, 'group'); // data is your initial collection

Ou si vous préférez ne pas utiliser de bibliothèque, vous pouvez le faire vous-même:

var groups = { };
data.forEach(function(item){
   var list = groups[item.group];

   if(list){
       list.Push(item);
   } else{
      groups[item.group] = [item];
   }
});

Vous pouvez voir les deux exemples en action http://jsfiddle.net/nkVu6/3/

11
ppoliani

Si vous aimez travailler avec ES6 Map, alors c'est pour vous:

function groupBy(arr, prop) {
    const map = new Map(Array.from(arr, obj => [obj[prop], []]));
    arr.forEach(obj => map.get(obj[prop]).Push(obj));
    return Array.from(map.values());
}

const data = [{ name: "Display", group: "Technical detals", id: 60, value: 4 }, { name: "Manufacturer", group: "Manufacturer", id: 58, value: "Apple" }, { name: "OS", group: "Technical detals", id: 37, value: "Apple iOS" }];
        
console.log(groupBy(data, "group"));
.as-console-wrapper { max-height: 100% !important; top: 0; }

L'instance Map est créée à partir de paires clé/valeur générées à partir du tableau d'entrée. Les clés sont les valeurs de la propriété à regrouper et les valeurs sont initialisées sous forme de tableaux vides.

Ensuite, ces tableaux sont remplis. Enfin, les valeurs de la carte (c'est-à-dire les tableaux remplis) sont renvoyées.

11
trincot

Réduire est idéal pour des situations comme celle-ci. Étant donné list ci-dessous, vos données d'entrée:

const list = [{
    'name': 'Display',
    'group': 'Technical detals',
    'id': '60',
    'value': '4'
  },
  {
    'name': 'Manufacturer',
    'group': 'Manufacturer',
    'id': '58',
    'value': 'Apple'
  },
  {
    'name': 'OS',
    'group': 'Technical detals',
    'id': '37',
    'value': 'Apple iOS'
  }
];

const groups = list.reduce((groups, item) => {
  const group = (groups[item.group] || []);
  group.Push(item);
  groups[item.group] = group;
  return groups;
}, {});

console.log(groups);

Et si vous vouliez être immuable, vous pourriez écrire le reduce comme ceci:

const list = [{
    'name': 'Display',
    'group': 'Technical detals',
    'id': '60',
    'value': '4'
  },
  {
    'name': 'Manufacturer',
    'group': 'Manufacturer',
    'id': '58',
    'value': 'Apple'
  },
  {
    'name': 'OS',
    'group': 'Technical detals',
    'id': '37',
    'value': 'Apple iOS'
  }
];

const groups = list.reduce((groups, item) => ({
  ...groups,
  [item.group]: [...(groups[item.group] || []), item]
}), {});

console.log(groups);

Selon que votre environnement autorise la syntaxe étendue.

7
btomw

Vous pouvez utiliser une table de hachage pour les groupes et Array#forEach pour itérer le tableau.

Vérifiez ensuite si le hachage existe et sinon, affectez-lui un tableau vide et envoyez-le dans le jeu de résultats.

Plus tard Poussez l'élément réel dans le tableau du hachage.

function groupBy(array, group) {
    var hash = Object.create(null),
        result = [];

    array.forEach(function (a) {
        if (!hash[a[group]]) {
            hash[a[group]] = [];
            result.Push(hash[a[group]]);
        }
        hash[a[group]].Push(a);
    });
    return result;
}

var data = [{ name: "Display", group: "Technical detals", id: 60, value: 4 }, { name: "Manufacturer", group: "Manufacturer", id: 58, value: "Apple" }, { name: "OS", group: "Technical detals", id: 37, value: "Apple iOS" }];
        
console.log(groupBy(data, "group"));
.as-console-wrapper { max-height: 100% !important; top: 0; }
7
Nina Scholz

Utilisez réduire et filtre .

disons que votre tableau initial est affecté à data

data.reduce((acc, d) => {
    if (Object.keys(acc).includes(d.group)) return acc;

    acc[d.group] = data.filter(g => g.group === d.group); 
    return acc;
}, {})

cela vous donnera quelque chose comme

{
    "Technical detals" = [
    {
       'group'   = 'Technical detals',
       'name'    = 'Display',
       'id'      = '60',
       'value'   = '4'
    },
    {
       'group'   = 'Technical detals',
       'name'    = 'OS',
       'id'      = '37',
       'value'   = 'Apple iOS'
    }],
    "Manufacturer"   = [
    {
       'group'   = 'Manufacturer',
       'name'    = 'Manufacturer',
       'id'      = '58',
       'value'   = 'Apple'
    }]
}
2
Anthony Awuley

J'ai essayé d'utiliser la réponse marquée comme acceptée, mais j'ai remarqué qu'il manquait des éléments dans certains groupes, selon le type de bien évalué. C'est une solution dérivée de cette réponse:

function groupBy(collection, property) {
  var i = 0, values = [], result = [];
  for (i; i < collection.length; i++) {
    if(values.indexOf(collection[i][property]) === -1) {
      values.Push(collection[i][property]);
      result.Push(collection.filter(function(v) { return v[property] === collection[i][property] }));
    }
  }
  return result;
}
var obj = groupBy(list, "group");
0
buffolander

Essayer

let g = (d,h={},r={},i=0)=>(d.map(x=>(y=x.group,h[y]?1:(h[y]=++i,r[h[y]-1]=[]),r[h[y]-1].Push(x))),r);
console.log( g(data) );
let data=[
  {
    "name":"Display",
    "group":"Technical detals",
    "id":"60",
    "value":"4"
  },
  {
    "name":"Manufacturer",
    "group":"Manufacturer",
    "id":"58",
    "value":"Apple"
  },
  {
    "name":"OS",
    "group":"Technical detals",
    "id":"37",
    "value":"Apple iOS"
  }
];


let g = (d,h={},r={},i=0)=>(d.map(x=>(y=x.group,h[y]?1:(h[y]=++i,r[h[y]-1]=[]),r[h[y]-1].Push(x))),r);

console.log(g(data));
0
Kamil Kiełczewski

Si vous utilisez lodash, vous pouvez utiliser groupBy .

Il prend en charge à la fois le tableau et l'objet.

Exemple:

_.groupBy([6.1, 4.2, 6.3], Math.floor);
// => { '4': [4.2], '6': [6.1, 6.3] }

// The `_.property` iteratee shorthand.
_.groupBy(['one', 'two', 'three'], 'length');
// => { '3': ['one', 'two'], '5': ['three'] }
0
Hongbo Miao