简体   繁体   中英

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. 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; I simple do a ToList() to have them as lists.

How can I get the right result, with using the Lists (or Iqueryables if the ToList() is unneccessary?

Thanks in advance!

I think I got what you want - you want to not apear any id twice. 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. And the, with Union (Excludes duplicates), it merges List2. ToList() might be optional, depending on what you're doing next with it.

EDIT: Changed form Concat to Union.

You could try to find the first matching ParentId from List2 while iterating List1, and add depending if it was found or not:

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:

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:

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).

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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