7
votes

Groupe par plage de dates, comptez et triez dans chaque groupe LINQ

J'ai une collection de dates stockées dans mon objet. Ceci est l'exemple de données. En temps réel, les dates proviendront d'un appel de service et je n'aurai aucune idée de quelles dates et combien seront retournées: xxx pré>

J'ai maintenant besoin de grouper par plage de date comme: xxx pré>

C'est ma déclaration de Linq qui ne réalise pas ce dont j'ai besoin, mais je pense que je suis dans le ballon (soyez gentil si je ne suis pas): p>

                   var defaultGroups = from l in ListHeader
                                    group l by l.EntryDate into g
                                    orderby g.Min(x => x.EntryDate)
                                    select new { GroupBy = g };


0 commentaires

4 Réponses :


5
votes

Que diriez-vous de cela?

Introduisez une nouvelle propriété pour le groupement et le groupe par cela. P>

 var defaultGroups = from l in ListHeader
     group l by l.DateDifferenceFromToday into g // <--Note group by DateDifferenceFromToday
     orderby g.Min(x => x.EntryDate)
     select new { GroupBy = g };


12 commentaires

@Jimballard vient de voir votre profil. OMG 30+ ans d'expérience dans le logiciel? Je n'ai pas encore traversé 30 ans!


Ha! Mon premier code était sur des cartes de poinçon introduites dans un IBM 360. Le 360 ​​était neuf et de pointe!


J'éviterais d'utiliser un int pour cela; Le lecteur du code n'aura aucune idée de ce que cela signifie. Utilisez quelque chose comme un Enum pour cela; C'est pareil à un ordinateur, mais ce sera beaucoup plus lisible. En outre, il n'y a aucune raison de créer un nouveau type anonyme juste pour y mettre le groupe. Si vous n'avez besoin que du groupe, sélectionnez simplement le groupe.


@Servy Oui Type anonyme est redondant ici, je viens de copier le code de l'OP. Je vais envisager énum dans ma réponse


@Servy mis à jour avec une énumération. J'espère que maintenant il semble plus lisible


Merci d'avoir répondu, mais je ne peux pas donner de données d'un disque dur. J'ai des données codées dures à des fins d'échantillonnage. Je ne sais pas combien de dates le service sera de retour, alors j'ai besoin du regroupement, triant le comptage de publicité réalisée à Linq


Vous ne devriez pas comparer totaldays à 0 pour obtenir "aujourd'hui". C'est un double ; Ça va avoir une journée fractionnée pour toute journée partielle. Vous voulez moins d'un à la place


@ user1202717 Donc, vos gammes de date sont dynamiques? Si oui, comment savez-vous ce qu'ils sont?


@Servy Non, vous devez noter DateTime.today - entréeDate.date La partie fractionnelle est donc ignorée ici la précision est à jour. Je peux comparer de manière fiable totaldays à 0


Mes chaînes de date seront sous formes (2 dernières semaines, le mois dernier, l'an dernier). Donc, le service retournera les dates de la plage sélectionnée, puis j'en ai besoin de regroupement, triés et comptés. Je traite avec beaucoup de données, donc il y aura beaucoup de dattes retournées.


@ user1202717 Vous n'avez toujours pas décrit comment déterminer quel groupe appartient un article, car une personne laissera seule un ordinateur. Vous devez commencer ici.


Vous définissez donc 2 dernières semaines, le mois dernier, l'année dernière etc. n'est-ce pas? Définissez la même chose dans Enum et modifier la propriété en conséquence



1
votes

Voulez-vous spécifiquement d'atteindre la solution de cette manière? Voulez-vous également vraiment introduire des propriétés parasites dans votre classe pour répondre à ces exigences?

Ces trois lignes permettraient de réaliser vos besoins et que les grandes collections ne seront plus performantes. P>

Group            Count
Today            1 
LessThanTwoWeeks 3 
MoreThanTwoWeeks 2 


1 commentaires

Merci d'avoir répondu. Comment puis-je trier (ordonnance) les groupes?



7
votes

Introduisez le tableau, qui contient des gammes que vous souhaitez grouper. Voici deux gammes - aujourd'hui (zéro jours) et 14 jours (deux semaines): xxx

regroupez maintenant vos articles en intervalle de portée. S'il n'y a pas de plage appropriée (toutes les dates plus de deux semaines), la valeur par défaut null NULL sera utilisée: xxx

mise à jour: Ajout de gammes personnalisées Pour le groupement: xxx


9 commentaires

Basé sur les commentaires de l'OP, il semble que les groupements de jours ne soient pas exclusivement dans un nombre fixe de jours, c'est-à-dire qu'il mentionne le mois dernier, qui est un nombre variable de jours.


@Servy merci, je n'ai pas encore vu des commentaires sur d'autres réponses. Laissez-moi vérifier cela.


@Servy je ne vois aucun problème à remplir la liste des gammes avec des besoins de valeur optables. Par exemple. Pour CurrentMonth, vous devez ajouter DateTime.today.day à la liste. De plus, si cela est inconnu, ce que les gammes seront ajoutées, la liste des plages doit être triée avant de interroger.


@lazybereezovsky - J'aime beaucoup cette approche, mais comment puis-je trier les groupes individuels ASC / DESC?


@ user1202717 Vous pouvez commander chaque groupe lors de leur énumérer avec foreach (var h dans g.orderby (x => x)) . Ou vous pouvez sélectionner le type anonyme au lieu de la sélection de groupe: Sélectionnez Nouvelle {plage = g.key, éléments = g. (x => x)} qui aura une gamme et des articles commandés


@lazybereezovsky - c'est exactement ce que je voulais. Merci beaucoup


Avez-vous une idée de la manière de trier par date au sein du groupe?


@ROMIAS SELECT g.orderby (x => x.Entrydate)


Pour EF 6, il faut utiliser dbfonctions.diff laisser jourfromtoday = dbfonctions.diffdays (h.Enrydate, aujourd'hui)



0
votes

Je suppose que cela dépend de la difficulté que vous envisagez de l'utiliser. J'avais / avoir beaucoup de rapports à générer afin que j'ai créé un modèle incrémentdaterange avec starttime , endtime et time-crème EnumM,

Le gestionnaire d'incrémentation de l'heure a beaucoup de fonctions basées sur le commutation crache une liste de temps entre la plage de début et de fin en fonction de l'heure / jour / semaine / mois / quart / année, etc. < p> Ensuite, vous obtenez votre liste de incrémentdaterange et dans linq quelque chose comme: xxx

ou xxx


0 commentaires