gpt4 book ai didi

c# - 对具有复杂类型的多个属性进行 GroupBy

转载 作者:行者123 更新时间:2023-12-02 17:24:54 25 4
gpt4 key购买 nike

我写了一个 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())
...

但这给了我

The type arguments cannot be inferred from the usage. Try specifying the type arguments explicitly.

我不知道下一步该怎么做,这样的分组应该不会太困难吧?

最佳答案

Enumerable.GroupBy 允许您传递键的自定义相等比较器。但在您的情况下,键不是 Address 对象 - 它是一个包含三个属性的匿名对象 - SiteRefNumSiteRefNameAddress.当然,传递 AddressComparer 来比较这些键会导致错误。

您的第一个问题是使用复杂对象作为关键属性。如果您不重写 Address 对象的 EqualsGetHashCode 方法,则将通过引用比较所有地址。这对于每个地址实例当然是不同的。您可以提供 EqualsGetHashCode 实现来比较地址。

或者您可以修改查询以使用地址字符串进行分组:

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# - 对具有复杂类型的多个属性进行 GroupBy,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42650526/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com