【问题标题】:LINQ for comparing two lists with complex entitiesLINQ 用于将两个列表与复杂实体进行比较
【发布时间】:2013-12-17 13:47:49
【问题描述】:

我们有一个如下所列的类结构

public class ItemDTO
{
    public int ItemID { get; set; }
}


public class CostPageDTO
{
    public string CostPageNumber { get; set; }
    public List<ItemDTO> Items { get; set; }
}

有两个列表 – 1) 数据库中存在的成本页和项目列表 2) 用户选择的成本页

问题

我们需要比较这两个列表并得到一个结果列表,其中包含实际集合和选定集合中不同项目的计数相同的成本页。

best performing LINQ 是什么(在链式方法中)?

预期结果

基于以下场景的预期结果是一个只有 1 个成本页的列表 - “C2”(项目匹配)

代码

static void Main(string[] args)
{

    List<CostPageDTO> selectedCostPageAndItems = GetSelectedCostPageAndItems();
    List<CostPageDTO> actualItems = GetActualItems();

    //LINQ code to get the matching count costPages

}


private static List<CostPageDTO> GetSelectedCostPageAndItems()
{
    ItemDTO i1 = new ItemDTO();
    i1.ItemID = 1;

    ItemDTO i2 = new ItemDTO();
    i2.ItemID = 2;

    ItemDTO i3 = new ItemDTO();
    i3.ItemID = 3;


    CostPageDTO c1 = new CostPageDTO();
    c1.CostPageNumber = "C1";
    c1.Items = new List<ItemDTO>();
    c1.Items.Add(i1);

    CostPageDTO c2 = new CostPageDTO();
    c2.CostPageNumber = "C2";
    c2.Items = new List<ItemDTO>();
    c2.Items.Add(i2);
    c2.Items.Add(i3);

    //CostPageDTO c2Duplicate = new CostPageDTO();
    //c2Duplicate.CostPageNumber = "C2";
    //c2Duplicate.Items = new List<ItemDTO>();
    //c2Duplicate.Items.Add(i2);
    //c2Duplicate.Items.Add(i3);

    List<CostPageDTO> selectedCostPageAndItems = new List<CostPageDTO>();
    selectedCostPageAndItems.Add(c1);
    selectedCostPageAndItems.Add(c2);
    //selectedCostPageAndItems.Add(c2Duplicate);

    return selectedCostPageAndItems;

}
private static List<CostPageDTO> GetActualItems()
{
    ItemDTO i1 = new ItemDTO();
    i1.ItemID = 1;

    ItemDTO i2 = new ItemDTO();
    i2.ItemID = 2;

    ItemDTO i3 = new ItemDTO();
    i3.ItemID = 3;

    ItemDTO i3Duplicate = new ItemDTO();
    i3Duplicate.ItemID = 3;

    CostPageDTO c1 = new CostPageDTO();
    c1.CostPageNumber = "C1";
    c1.Items = new List<ItemDTO>();
    c1.Items.Add(i1);
    c1.Items.Add(i2);
    c1.Items.Add(i3);

    CostPageDTO c2 = new CostPageDTO();
    c2.CostPageNumber = "C2";
    c2.Items = new List<ItemDTO>();
    c2.Items.Add(i2);
    c2.Items.Add(i3);
    c2.Items.Add(i3Duplicate);

    List<CostPageDTO> actualItems = new List<CostPageDTO>();
    actualItems.Add(c1);
    actualItems.Add(c2);

    return actualItems;

}

【问题讨论】:

    标签: c# linq


    【解决方案1】:

    这将选择您的预期结果:

    方法语法:

    var result = selectedCostPageAndItems.SelectMany(scp => actualItems.Where(acp=>acp.CostPageNumber == scp.CostPageNumber),
                                (scp,acp)=> new {CostPageNumber = scp.CostPageNumber,
                                            scpItems = new HashSet<int>(scp.Items.Select(x=>x.ItemID)),
                                            acpItems = new HashSet<int>(acp.Items.Select(x=>x.ItemID))})
                            .Where(x => x.scpItems.SetEquals(x.acpItems))
                            .Select(x => x.CostPageNumber);
    

    查询理解语法:

    var result = from cp1 in selectedCostPageAndItems
                 from cp2 in actualItems
                 let items1 = new HashSet<int>(cp1.Items.Select(x=>x.ItemID))
                 let items2 = new HashSet<int>(cp2.Items.Select(x=>x.ItemID))
                 where cp1.CostPageNumber == cp2.CostPageNumber
                 && items1.SetEquals(items2)
                 select cp1.CostPageNumber;
    

    说明:

    找到所有选定的 (scp) 和实际 (acp) CostPageDTO 与相同的CostPageNumber

    selectedCostPageAndItems.SelectMany(scp => actualItems.Where(acp=>acp.CostPageNumber == scp.CostPageNumber)
    

    对于每个这样的对(scpacp),为选定的 (scpItems) 和实际的 (acpItems) CostPageDTO 选择 CostPageNumber 和一组 ItemDTO.ItemID

    (scp,acp)=> new {CostPageNumber = scp.CostPageNumber,
                                        scpItems = new HashSet<int>(scp.Items.Select(x=>x.ItemID)),
                                        acpItems = new HashSet<int>(acp.Items.Select(x=>x.ItemID))})
    

    最后选择具有相同集合的CostPageNumber

    Where(x => x.scpItems.SetEquals(x.acpItems)).Select(x => x.CostPageNumber)
    

    HashSet的创建和比较都是O(n)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多