1
votes

Comment groupby par deux champs du tableau en utilisant rxjs?

J'ai un tableau contenant 4 champs et je dois regrouper par deux propriétés et agréger (additionner) l'un des champs du tableau groupé.

J'ai essayé de grouper par plus d'un ne fonctionne pas.

le code ci-dessous J'ai essayé de manipuler le tableau dans la liste attendue, mais je ne sais pas comment obtenir le résultat attendu ci-dessous en utilisant RxJs

[{
            category : "Printer",
            subCategory : "A",
            manDate : "02/01/2019",
            amount : 190            
          },{
            category : "Printer",
            subCategory : "A",
            manDate : "02/03/2019",
            amount : 90            
          },{
            category : "Printer",
            subCategory : "A",
            manDate : "02/04/2019",
            amount : 90            
          },{
            category : "Scanner",
            subCategory : "A",
            manDate : "08/21/2019",
            amount : 63            
          }]

Array existant:

[{
        category : "Printer",
        manDate : "02/01/2019",
        amount : 90            
      },
      {
        category : "Printer",
        manDate : "02/01/2019",
        amount : 100            
      },
      {
        category : "Printer",
        manDate : "02/03/2019",
        amount : 90            
      },
      {
        category : "Printer",
        manDate : "02/04/2019",
        amount : 90            
      },
      {
        category : "Scanner",
        manDate : "08/21/2019",
        amount : 8            
      },
      {
        category : "Scanner",
        manDate : "08/21/2019",
        amount : 25            
      },
      {
        category : "Scanner",
        manDate : "08/21/2019",
        amount : 20            
      },
      {
        category : "Scanner",
        manDate : "08/21/2019",
        amount : 10            
      }

    ];

attendu:

from(this.dummyData)
        .pipe(
          groupBy(
            function (e) {
                return { category: e.category, manDate: e.manDate };   //is this valid at all?
            },
            function (e) { return e; }), 
            mergeMap(group => zip(of(group.key), group.pipe(toArray())))
        )
        .subscribe( function(result) {
          console.log(result);
        });

J'ai besoin de l'aide de quelqu'un pour obtenir ce résultat.


0 commentaires

3 Réponses :


1
votes
from(dummyData)
  .pipe(
    groupBy(// Group them by category and return the appropriate Arrays
      val => val.category
    ),
    mergeMap(group => {
      return group.pipe(toArray());
    }),
    mergeMap((array) => {// Take each from above array and group each array by manDate
      return from(array).pipe(groupBy(
        val => val.manDate,
        ),
        mergeMap(group => {
          return group.pipe(toArray()); // return the group values as Arrays
        })
      );
    }),
    map((val) => { //For each array returned , calculate the sum and map it to the Object you wanted
      let amount = 0;
      val.map(v => {
        amount = amount + v.amount;
      });
      return {category: val[0].category, manDate: val[0].manDate, amount};
    }),
    toArray() //finally combine all returned objects to an array
  ).subscribe(
    val => console.log(val)
);
It was hard to wrap my head around it but it seems to work. If it helped , dont forget to upvote, thanks! 

3 commentaires

map ((val) =>, il y a une erreur dans la fonction de carte, pourriez-vous s'il vous plaît la corriger


@ Gopinath2105 où?


testé et cela semble fonctionner sans erreur. Si cela a résolu votre problème, pourriez-vous marquer ma réponse comme acceptée?



1
votes

Essayez cette méthode, voyez si elle répond à vos besoins. Vous n'avez pas besoin de regroupement Rxjs IMO. Et il y a probablement plus de façons de manipuler le tableau d'entrée pour la sortie souhaitée, mais c'est ma solution relativement rapide et facile à lire. Dites-moi comment cela s’adapte à votre cas :)

  transform(array: Array<any>) {
    const newArray = [];
    array.forEach(item => {
      const index = newArray.findIndex(
        i => i.category === item.category && i.manDate === item.manDate
      );
      if (index >= 0) {
        newArray[index].amount += item.amount;
      } else {
        newArray.push(item);
      }
    });
    return newArray;
  }


3 commentaires

La question dit spécifiquement avec rxjs et apprendre Rxjs est une compétence cruciale lors de l'utilisation d'angular. Le recours à l'état d'esprit impératif sera un inconvénient lorsque vous devrez résoudre des problèmes en utilisant uniquement le paradigme de programmation réactive rxjs.


@Jensen En effet, apprendre Rxjs est une compétence cruciale pour un développeur Angular, mais savoir quand utiliser quels outils est aussi important (c'est-à-dire généralement pour un développeur). Parfois, il peut ne pas être nécessaire de convertir un tableau en observable, de le manipuler à l'aide de Rxjs, puis de s'abonner à l'observable, lorsque des solutions plus simples peuvent le faire. Si la question ci-dessus concerne l'apprentissage de Rxjs, alors ce n'est pas la meilleure façon d'apprendre Rxjs. Si c'est la fonctionnalité recherchée par l'utilisateur, j'ai fourni une solution plus simple que Rxjs. :)


À partir de cet exemple lui-même, je viens d'apprendre à utiliser le canal de groupe et à utiliser efficacement toArray (). À mon avis, essayer les choses de manière réactive est un must sinon lorsque vous serez confronté à un problème qui ne peut être résolu impérativement, vous serez bloqué. Encore une fois, ce passage de l'état d'esprit impératif à l'état d'esprit réactif ne se fera pas facilement et nécessite beaucoup de pratique. Je ne comprends pas pourquoi la question demande spécifiquement «en utilisant rxjs» si ce n'est dans le but d'apprendre? Il est clair que cela n'a rien à voir avec la gestion des données basée sur les événements ou asynchrone.



0
votes

Je pense que nous pouvons utiliser ici réduire.

from(dummyData)
.pipe(
groupBy( val => val.category ), // Group them by category and return the appropriate Arrays
mergeMap(group => { return group.pipe(toArray()); }),
mergeMap((array) => {// Take each from above array and group each array by manDate
  return from(array).pipe( 
    groupBy( val => val.manDate, ),
    mergeMap(group => {
      return group.pipe(toArray()); // return the group values as Arrays
    })
  );
}),
mergeMap((array) => {// Take each from above array and group each array by manDate
  return from(array).pipe( 
    reduce((acc, curr) => ({
        category: curr.category, 
        manDate: curr.manDate,
        amount: curr.amount + acc.amount
    }), { category: '', manDate: '', amount: 0})
  );
}),   
).subscribe(
val => console.log(val));


1 commentaires

salut et bienvenue sur StackOverflow! il existe déjà une réponse acceptée à cette question.