我写了这样的GroupBy语句:
var aggregated = sitesWithLive
.GroupBy(s => new {s.SiteRefNum, s.SiteRefName, s.Address})
.Select(g =>
new Site
{
SiteRefNum = g.Key.SiteRefNum,
SiteRefName = g.Key.SiteRefName,
Address = g.Key.Address,
ContractLive = g.Max(x => x.ContractLive)
});
分组中的
Address
是复杂类型:public class Address
{
public string Name { get; set; }
public string Line1 { get; set; }
public string Line2 { get; set; }
public string Line3 { get; set; }
public string Line4 { get; set; }
public string PostCode { get; set; }
public bool IsEmpty()
{
return GetType().GetProperties()
.Where(a => a.GetValue(this) is string)
.Select(a => (string)a.GetValue(this))
.All(string.IsNullOrEmpty);
}
public override string ToString()
{
var addr = Line1 + "," + Line2 + "," + Line3 + "," + Line4 + "," + PostCode;
var address = Regex.Replace(addr, @"^,+|,{2,}|,(?=[\w.])", ", ");
return address;
}
}
但是,这不能按地址正确分组,而是为每个元素返回一个单独的组。
据我了解,要按复杂类型分组,必须提供
IEqualityComparer
,因此我创建了以下内容:public class AddressComparer : IEqualityComparer<Address>
{
public bool Equals(Address x, Address y)
{
return x.ToString() == y.ToString();
}
public int GetHashCode(Address obj)
{
return 1;
}
}
并像这样提供(上面的子集):
var aggregated = sitesWithLive.GroupBy(s => new {s.SiteRefNum, s.SiteRefName, s.Address}, new AddressComparer())
...
但是这给了我
不能从用法中推断出类型实参。尝试指定
类型参数明确。
我对下一步不知所措,这种分组肯定不会太难吗?
最佳答案
Enumerable.GroupBy
允许您传递键的自定义相等比较器。但是在您的情况下,密钥不是Address
对象-它是包含三个属性-SiteRefNum
,SiteRefName
和Address
的匿名对象。当然,传递AddressComparer
来比较此类键将导致错误。
您的第一个问题是使用复杂对象作为关键属性。如果不为Equals
对象覆盖GetHashCode
和Address
方法,则将通过引用比较所有地址。对于每个地址实例,这当然是不同的。您可以提供Equals
和GetHashCode
实现来比较地址。
或者,您可以修改查询以使用地址字符串进行分组:
var aggregated =
from s in sitesWithLive
group s by new {
s.SiteRefNum,
s.SiteRefName,
Address = s.Address.ToString() // here we group by string
} into g
select new Site
{
SiteRefNum = g.Key.SiteRefNum,
SiteRefName = g.Key.SiteRefName,
Address = g.First().Address, // here we just get first address object
ContractLive = g.Max(x => x.ContractLive)
};
您可以使用方法语法进行查询,但是我发现声明性查询语法更易读:)
关于c# - 对具有复杂类型的多个属性进行分组,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42650526/