So integrieren Sie das Feld List <string> in GroupBy ()
Ich habe eine Liste von Diff-Objekten. Diff sieht so aus
public class Diff
{
ChangeAction Action // ChangeAction is an Enum
string Type
DateTime StartDateTime
DateTime EndDateTime
int rateId
string rateDescription
List<string> properties
DayOfWeek day
List<DaysOfWeek> DaysOfWeek
DayOfWeek DayOfWeek
}
Meine LINQ-Abfrage macht nicht das, was ich denke. Ich bin vorbei in diff.propertiesin dem GroupBy(), der eine Liste ist und ich mag es Gruppe , wenn all String - Wert in einer Liste Spiel
var results = diffs
.GroupBy(diff => new { diff.properties, diff.Action, diff.Type, diff.StartDateTime,
diff.EndDateTime, diff.rateId, diff.rateDescription})
.Select(group => new Diff(
group.Key.Action,
group.Key.ScheduleType,
group.Key.StartDateTime,
group.Key.EndDateTime,
group.Key.rateId,
group.Key.rateDescription,
group.Key.properties,
group
.Select(ts => ts.DayOfWeek)
.Distinct()
.OrderBy(dow => dow)
.ToList()))
.ToList();
Der einzige Unterschied zwischen resultsund diffsbesteht darin, dass der DayOfWeekzuvor gespeicherte Singular diffsjetzt in das Pluralfeld DaysOfWeekeingefügt wird (aber nur 1 Element in der Liste). Derzeit die gleiche Anzahl von Elementen in beiden resultsund diffs.
Was ich in der Ergebnisliste sehen möchte, sind:
- Eine kürzere Liste, die basierend auf dem Abgleich aller Gruppierungen konsolidiert wird (einschließlich der Listenwerte von diff.properties).
- Dies würde auch mehr als 1 Element in der DaysOfWeek-Liste bedeuten.
Meine Frage ist:
Wie kann ich meine LINQ-Abfrage oben ändern, um zu sehen, was ich sehen möchte results?
Antworten
Die Gruppierung, die Sie mit dem anonymen Typ verwenden, enthält a List<string>, wodurch Sie einen 1-1-Satz ohne Gruppierung erhalten.
Sie müssen entweder
- Verwenden Sie eine benutzerdefinierte Klasse für die Gruppierung und Überladung
GetHashCodeundEqualswie in dieser Frage gezeigt: Verwenden von LINQ GroupBy zum Gruppieren nach Referenzobjekten anstelle von Wertobjekten
- ODER -
- Erstellen Sie eine Zeichenfolge aus den ausgewählten Werten oder einer Teilmenge davon (
diff.properties, diff.Action, diff.Type, diff.startdatetime, diff.enddatetime, diff.rateId, diff.rateDescription), die als eindeutiger Schlüssel zum Gruppieren dient
Einige Ihrer GroupByEigenschaften sind Referenztypen, und der Standardvergleich für diese Typen ist ein Referenzvergleich, sodass keiner dieser Eigenschaften jemals übereinstimmt. Um dies zu überwinden, können wir unsere eigenen EqualityComparerfür die DiffKlasse schreiben, damit wir sie auf unsere eigene Weise vergleichen können:
public class DiffEqualityComparer : IEqualityComparer<Diff>
{
public bool Equals(Diff first, Diff second)
{
if (first == null || second == null) return ReferenceEquals(first, second);
if (first.Properties == null && second.Properties != null) return false;
if (first.Properties != null && second.Properties == null) return false;
if (first.Properties != null && second.Properties != null &&
!first.Properties.OrderBy(p => p)
.SequenceEqual(second.Properties.OrderBy(p => p)))
return false;
if (!first.Action.Equals(second.Action)) return false;
if (!string.Equals(first.Type, second.Type)) return false;
if (!first.Start.Equals(second.Start)) return false;
if (!first.End.Equals(second.End)) return false;
if (!first.RateId.Equals(second.RateId)) return false;
if (!string.Equals(first.RateDescription, second.RateDescription)) return false;
return true;
}
public int GetHashCode(Diff obj)
{
var hash = obj.Properties?.Aggregate(0,
(accumulator, current) => accumulator * 17 + current.GetHashCode()) ?? 0;
hash = hash * 17 + obj.Action.GetHashCode();
hash = hash * 17 + obj.Type?.GetHashCode() ?? 0;
hash = hash * 17 + obj.Start.GetHashCode();
hash = hash * 17 + obj.End.GetHashCode();
hash = hash * 17 + obj.RateId.GetHashCode();
hash = hash * 17 + obj.RateDescription?.GetHashCode() ?? 0;
return hash;
}
}
Und schließlich können wir diesen benutzerdefinierten Vergleicher in unserer GroupByMethode verwenden:
var results = diffs
.GroupBy(diff => new DiffEqualityComparer())
.Select( // rest of code omitted
Ich habe es gelöst!
Das Lesen einer anderen Frage und der Kommentare + Antworten in dieser Frage hat mir geholfen, es herauszufinden!
public class DiffComparer : IEqualityComparer<Diff>
{
public bool Equals(Diff x, Diff y)
{
return x.Action == y.Action &&
x.Type == y.Type &&
x.StartDateTime == y.StartDateTime &&
x.EndDateTime == y.EndDateTime &&
x.rateId== y.rateId &&
x.rateDescription == y.rateDescription &&
x.properties.SequenceEqual(y.properties);
}
public int GetHashCode(Diff x)
{
int hash = 17;
hash = hash * 23 + x.Action.GetHashCode();
hash = hash * 23 + x.Type.GetHashCode();
hash = hash * 23 + x.StartDateTime .GetHashCode();
hash = hash * 23 + x.EndDateTime.GetHashCode();
hash = hash * 23 + x.rateId.GetHashCode();
hash = hash * 23 + x.rateDescription.GetHashCode();
foreach (string prop in x.properties)
{
hash = hash * 31 + prop.GetHashCode();
}
return hash;
}
}
Und ich habe diese Änderung am LINQ vorgenommen:
var results = diffs
.GroupBy(diff => diff, new DiffComparer())
.Select(group => new Diff(
group.Key.Action,
group.Key.ScheduleType,
group.Key.StartDateTime,
group.Key.EndDateTime,
group.Key.rateId,
group.Key.rateDescription,
group.Key.properties,
group
.Select(ts => ts.DayOfWeek)
.Distinct()
.OrderBy(dow => dow)
.ToList()))
.ToList();