1

鉴于以下数据结构,我希望根据该列表本身的列表对列表进行分组:

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行在另一个组中?

谢谢。

4

1 回答 1

3

您可以按逗号分隔的详细 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等。

于 2013-09-30T07:58:45.617 回答