GroupBy () içindeki List <string> alanı nasıl dahil edilir
Diff nesnelerinin bir listesi var Diff buna benziyor
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
}
LINQ sorgum yapacağını düşündüğüm şeyi yapmıyor. Ben geçen am diff.properties
içinde GroupBy()
bir Liste olan ve grubuna istediğinizde bir liste maçında tüm dize değerleri
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();
Arasındaki tek fark results
ve diffs
tekil olmasıdır DayOfWeek
önceden depolanmış olan diffs
şimdi çoğul konur DaysOfWeek
alan (ancak listede sadece 1 öğe). Şu anda, her ikisinde de aynı öğe sayısı results
ve diffs
.
Sonuçlar listesinde görmek istediğim şeyler:
- Tüm gruplamalara göre eşleşmeye dayalı olarak konsolide eden daha kısa bir liste (fark. Özellikler listesi değerleri dahil)
- Bu aynı zamanda Haftanın Günleri listesinde 1'den fazla öğe anlamına gelir.
Sorum şu:
Ne görmek istediğimi görmek için yukarıdaki LINQ sorgumu nasıl değiştirebilirim results
?
Yanıtlar
Anonim türle kullandığınız gruplama List<string>
, 1-1 gruplanmamış bir küme elde etmenize neden olan bir içerir .
İkisine de ihtiyacın var
- gruplama ve aşırı yükleme için özel bir sınıf kullanın
GetHashCode
veEquals
bu soruda gösterildiği gibi: Değer nesneleri yerine referans nesnelere göre gruplamak için LINQ GroupBy'yi kullanma
- VEYA -
- değerlerden bir dize veya bunların bir alt kümesini oluşturarak,
diff.properties, diff.Action, diff.Type, diff.startdatetime, diff.enddatetime, diff.rateId, diff.rateDescription
grup için benzersiz bir anahtar görevi görecek ( )
Senin Birkaç GroupBy
özelliklerine referans türleri vardır ve bunların hiçbiri maç olacak böylece bu türleri için varsayılan karşılaştırıcısı, bir refernence karşılaştırmasıdır. Bunun üstesinden gelmek EqualityComparer
için, Diff
sınıf için kendimizinkini yazabiliriz, böylece onları kendi yöntemimizle karşılaştırabiliriz:
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;
}
}
Son olarak, bu özel karşılaştırıcıyı GroupBy
yöntemimizde kullanabiliriz:
var results = diffs
.GroupBy(diff => new DiffEqualityComparer())
.Select( // rest of code omitted
Ben çözdüm!
Başka bir soruyu okumak ve bu sorudaki yorumlar + cevaplar bunu anlamama yardımcı oldu!
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;
}
}
LINQ'da bu düzenlemeyi yaptım:
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();