我有这个对象:
notes:[
{ user: {
name: "A",
group:{
id:1,
name:"Group 1"
}
},
{ user: {
name: "B",
group:{
id:1,
name:"Group 1"
}
}]
我需要按组分组..所以我尝试了这个:
foreach (IGrouping<Group, Note> item in notes.GroupBy(n => n.User.Group))
{
var groupName = item.Key.Name;
foreach (var note in item)
{
//
}
}
但是我遇到了一个问题,因为分组不起作用(我认为这是因为它使用引用对复杂类型进行分组)。如果我通过n.User.GroupId
更改n.User.Group
它就可以工作,但是如果我这样做,我将无法获得组名。
您需要在组类中覆盖 Equals 和 GetHashCode。 R# 为其生成此类代码:
public class Group
{
public int GroupId { get; set; }
public string Name { get; set; }
protected bool Equals(Group other)
{
return GroupId == other.GroupId;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((Group) obj);
}
public override int GetHashCode()
{
return GroupId;
}
}
是的,这是正确的。 默认情况下,类都是唯一的,但是您可以覆盖唯一性。
- 覆盖组对象上的
Equals(object obj)
和GetHasCode()
以实现您自己的相等 - 实现
IEqualityComparer<Group>
并将其作为第三个参数传递给 GroupBy 方法。
这里有几个选择:
- 确保组对象的类实现 GetHashCode 和 Equals。实现这些可以像比较组内的 ID 一样简单
- 按 id 分组,并获取分组中第一个用户的组名称。所有分组用户都属于同一组,因此名称将相同
- 如果您无权访问组类的源代码,请根据包装的组的 id 按实现 GetHashCode 和 Equals 的包装器进行分组。
你利用比较匿名类的优势,写成
notes.GroupBy(n => new{n.User.Group.ID,n.User.Group.Name});