web-dev-qa-db-fra.com

Grouper par plusieurs valeurs Underscore.JS mais conserver les clés et les valeurs

J'essaie de regrouper le tableau suivant avec des objets:

[ { user_id: 301, alert_id: 199, deal_id: 32243 },
  { user_id: 301, alert_id: 200, deal_id: 32243 },
  { user_id: 301, alert_id: 200, deal_id: 107293 },
  { user_id: 301, alert_id: 200, deal_id: 277470 } ]

Comme vous pouvez le constater, il contient des combinaisons user_id et alert_id, que je préfère grouper. Donc j'aimerais avoir le tableau suivant:

[ { user_id: 301, alert_id: 199, deals: [32243] },
  { user_id: 301, alert_id: 200, deals: [32243,107293,277470]}]

Quelqu'un connaît une solution pour cela? Avec le trait de soulignement GroupBy, je peux regrouper les valeurs en fonction d'une clé. Mais je dois les regrouper, en fonction de la combinaison user_id AND alert_id, comme vous pouvez le voir.

J'ai jeté un coup d'œil à underscore.nest , mais le problème est qu'il crée ses propres clés.

32
Erik van de Ven

Utilisez groupBy avec une fonction qui crée une clé composite en utilisant user_id et alert_id. Puis mappez les groupes pour obtenir ce que vous voulez:

    var list = [ { user_id: 301, alert_id: 199, deal_id: 32243 },
      { user_id: 301, alert_id: 200, deal_id: 32243 },
      { user_id: 301, alert_id: 200, deal_id: 107293 },
      { user_id: 301, alert_id: 200, deal_id: 277470 } ];

    var groups = _.groupBy(list, function(value){
        return value.user_id + '#' + value.alert_id;
    });

    var data = _.map(groups, function(group){
        return {
            user_id: group[0].user_id,
            alert_id: group[0].alert_id,
            deals: _.pluck(group, 'deal_id')
        }
    });
80
Gruff Bunny

Je voudrais contribuer un groupe soigné TypeScript ES6 par.
Je ne sais pas trop comment resserrer la saisie de la valeur de retour. Il faut faire quelques manipulations, mais cela fonctionne plutôt bien pour moi.

/**
 * group the supplied list by a set of keys.
 * @param list the list of items to group.
 * @param children the key for the array of child items.
 * @param components the components to group by.
 */
groupByMultipleFields<T, K extends keyof T>(
    list: T[],
    children: string,
    ...components: K[]): any[] {

    var grouping = [...list.reduce((r, o) => {
        const key = components.map(_ => `${o[_]}`).join(" :: ");
        var keyed = r.get(key) || components.reduce((x, y) => { x[y] = o[y]; return x; }, <T>{});
        keyed[children] = keyed[children] || [];
        keyed[children].Push(o);
        return r.set(key, keyed);
    }, new Map).values()];
    return grouping;

}

Vous devrez activer l'option "downlevelIteration": true du compilateur TypeScript pour permettre au new Map d'itérer et de renvoyer values().

0
Jim