简体   繁体   English

合并两个对象列表,但根据不同的值删除重复项

[英]Union two lists of object but remove duplicates based on different values

I have two lists of objects: 我有两个对象列表:

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

I want to return a union list of these two, but without the ones of List1 that are in List2 with its id as parentId. 我想返回这两个的联合列表,但不包含ID为parentId的List2中的List1。 My result in above example would be: 我在上面的示例中的结果是:

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

One extra thing: the two list initially are two IQueryables; 还有一件事情:这两个列表最初是两个IQueryable。 I simple do a ToList() to have them as lists. 我简单地做一个ToList()将它们作为列表。

How can I get the right result, with using the Lists (or Iqueryables if the ToList() is unneccessary? 如何使用列表(如果不需要ToList(),则可以使用Iqueryables)获得正确的结果?

Thanks in advance! 提前致谢!

I think I got what you want - you want to not apear any id twice. 我想我得到了您想要的-您不想再次出现任何ID。 So if some "parent" is used in field "parent" you dont whant it extra in the result? 因此,如果在字段“父母”中使用了一些“父母”,您是否不希望结果中额外包含它?

in this case, you can do this: 在这种情况下,您可以执行以下操作:

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

The Where-part excludes all items, that are used as parents in List2. “位置”部分排除了所有在List2中用作父项的项目。 And the, with Union (Excludes duplicates), it merges List2. 然后,通过Union(排除重复项)合并List2。 ToList() might be optional, depending on what you're doing next with it. ToList()可能是可选的,具体取决于下一步要执行的操作。

EDIT: Changed form Concat to Union. 编辑:将表格Concat更改为Union。

You could try to find the first matching ParentId from List2 while iterating List1, and add depending if it was found or not: 您可以尝试在迭代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);
}

Or with only LINQ: 或仅使用LINQ:

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

You can use System.Linq extension methods Union (to get the union of two lists) along with Where and All to filter out the items you don't want to include from the first list: 您可以使用System.Linq扩展方法Union (以获取两个列表的并集)以及WhereAll来从第一个列表中过滤出不想包含的项目:

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

But please note that Union will use the Equals method of the class to determine if two items match (which by default is a reference comparison), so you would need to override Equals and GetHashCode in order to remove duplicates (where a duplicate would be defined by you, in this case I guess would be defined where the Id properties of two items matched, but maybe you would include ParentId as well). 但是请注意, Union将使用该类的Equals方法确定两个项目是否匹配(默认情况下是引用比较),因此您需要重写EqualsGetHashCode才能删除重复项(其中将定义一个重复项)由您决定,在这种情况下,我想应该在两个项目的Id属性匹配的地方定义,但也许您也会包括ParentId )。

For example: 例如:

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;
    }
}

And then an example usage would be: 然后一个示例用法是:

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...");
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM