考虑到以下数据结构,我希望根据列表中的列表对列表进行分组:
public class AccDocumentItem
{
public string AccountId {get;set;}
public List<AccDocumentItemDetail> DocumentItemDetails {get;set;}
}
和
public class AccDocumentItemDetail
{
public int LevelId {get;set;}
public int DetailAccountId {get;set;}
}
我现在有一个List<AccDocumentItem>
由15个项目组成,每个项目都有一个可变数量为AccDocumentItemDetail
的列表,问题是可能有AccDocumentItems
个相同AccDocumentItemDetails
,因此我需要将List<AccDocumentItem>
分组为AccDocumentItemDetail
列表。
为了更清楚,假设我的List<AccDocumentItem>
列表中的前3个(15个)元素是:
1:{
AccountId: "7102",
DocumentItemDetails:[{4,40001},{5,40003}]
}
2:{
AccountId: "7102",
DocumentItemDetails:[{4,40001},{6,83003},{7,23423}]
}
3:{
AccountId: "7102",
DocumentItemDetails:[{4,40001},{5,40003}]
}
如何将List<AccDocumentItem>
按DocumentItemDetails
列表分组,以便行 1 和 3 在他们自己的组中,并且 2 在另一组?
感谢。
答案 0 :(得分:3)
您可以使用逗号分隔的detail-ID字符串进行分组:
var query = documentItemList
.GroupBy(aci => new{
aci.AccountId,
detailIDs = string.Join(",", aci.DocumentItemDetails
.OrderBy(did => did.DetailAccountId)
.Select(did => did.DetailAccountId))
});
另一种更优雅,高效,可维护的方法是创建自定义IEqualityComparer<AccDocumentItem>
:
public class AccDocumentItemComparer : IEqualityComparer<AccDocumentItem>
{
public bool Equals(AccDocumentItem x, AccDocumentItem y)
{
if (x == null || y == null)
return false;
if (object.ReferenceEquals(x, y))
return true;
if (x.AccountId != y.AccountId)
return false;
return x.DocumentItemDetails
.Select(d => d.DetailAccountId).OrderBy(i => i)
.SequenceEqual(y.DocumentItemDetails
.Select(d => d.DetailAccountId).OrderBy(i => i));
}
public int GetHashCode(AccDocumentItem obj)
{
if (obj == null) return int.MinValue;
int hash = obj.AccountId.GetHashCode();
if (obj.DocumentItemDetails == null)
return hash;
int detailHash = 0;
unchecked
{
foreach (var detID in obj.DocumentItemDetails.Select(d => d.DetailAccountId))
detailHash = detailHash * 23 + detID;
}
return hash + detailHash;
}
}
现在您可以将其用于GroupBy
:
var query = documentItemList.GroupBy(aci => aci, new AccDocumentItemComparer());
您也可以将其用于许多其他Linq扩展方法,例如Enumerable.Join
等。