【问题标题】:Union two lists of object but remove duplicates based on different values合并两个对象列表,但根据不同的值删除重复项
【发布时间】:2019-08-09 00:12:32
【问题描述】:

我有两个对象列表:

List1 = [ {id: 1, parentId: null}, {id:2, parentId: null} ]
List2 = [ {id: 3, parentId: 1} ]

我想返回这两个的联合列表,但没有 List2 中的 ID 为 parentId 的 List1 的联合列表。我在上面的例子中的结果是:

UnionList = [ {id:3, parentId: 1}, {id:2, parentId: null} ]

还有一点:这两个列表最初是两个 IQueryable;我简单地做一个 ToList() 将它们作为列表。

如果 ToList() 是不必要的,我如何使用列表(或 Iqueryables)获得正确的结果?

提前致谢!

【问题讨论】:

  • 我不明白为什么{id: 1, parentId: null} 不在联盟中
  • 你尝试了什么?我们不是在做你的工作 - 这是思考、尝试、再思考。
  • 请提供可重现的代码示例(即包含一个简单的类定义,填充两个列表,显示您尝试过的内容,然后显示您的结果并描述预期结果)

标签: c# list linq iqueryable


【解决方案1】:

您可以使用System.Linq 扩展方法Union(获取两个列表的并集)以及Where 和All 从第一个列表中过滤掉您不想包含的项目:

var result = list2.Union(list1.Where(l1 => list2.All(l2 => l2.ParentId != l1.Id)));

但请注意Union 将使用类的Equals 方法来确定两个项目是否匹配(默认情况下是参考比较),因此您需要覆盖Equals 和GetHashCode in为了删除重复项(重复项将由您定义,在这种情况下,我猜将定义两个项目的 Id 属性匹配的位置,但也许您也将包括 ParentId)。

例如:

public class Item
{
    public int Id { get; set; }
    public int? ParentId { get; set; }

    public override int GetHashCode()
    {
        return Id.GetHashCode();
    }

    public override bool Equals(object obj)
    {
        return Id == (obj as Item)?.Id;
    }
}

然后一个示例用法是:

public class Program
{
    private static void Main(string[] args)
    {
        var list1 = new List<Item>
        {
            new Item {Id = 1, ParentId = null},
            new Item {Id = 2, ParentId = null},
            new Item {Id = 3, ParentId = 1}
        };

        var list2 = new List<Item>
        {
            new Item {Id = 3, ParentId = 1}
        };

        var result = list2.Union(list1.Where(l1 => list2.All(l2 => l2.ParentId != l1.Id)));

        GetKeyFromUser("\nDone! Press any key to exit...");
    }
}

【讨论】:

    【解决方案2】:

    我想我得到了你想要的——你不想让任何身份出现两次。因此,如果在“父”字段中使用了某些“父”,您不需要在结果中额外添加它吗?

    在这种情况下,您可以这样做:

    var result = List1.Where(x => !List2.Any(l2 => l2.parentId == x.id)).Union(List2);//.ToList();
    

    Where 部分不包括在 List2 中用作父项的所有项。并且,使用联合(排除重复项),它合并了 List2。 ToList() 可能是可选的,具体取决于您接下来要做什么。

    编辑:将 Concat 更改为 Union。

    【讨论】:

    • 从问题的“发言”来看,我的印象是无论如何都只是合并两个列表,这就是原因。但你是对的,联合会更好地满足需求。
    【解决方案3】:

    您可以尝试在迭代 List1 时从 List2 中找到第一个匹配的 ParentId,并根据是否找到它来添加:

    var UnionList = new List<Item>();
    foreach (var item in List1)
    {
        var match = List2.FirstOrDefault(x => x.ParentId == item.Id);
        resultList.Add(match ?? item);
    }
    

    或仅使用 LINQ:

    var UnionList = new List<Item>(List1.Select(item => List2.FirstOrDefault(x => x.ParentId == item.Id) ?? item));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-23
      • 2021-08-15
      • 2010-11-22
      • 2015-11-29
      • 2017-06-05
      • 1970-01-01
      • 2021-01-10
      • 2016-08-31
      相关资源
      最近更新 更多