Объединение двух списков объектов, но удаление дубликатов на основе разных значений - PullRequest
0 голосов
/ 18 марта 2019

У меня есть два списка объектов:

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

Я хочу вернуть объединенный список этих двух, но без списков List1, которые есть в List2 с его идентификатором parentId.Мой результат в приведенном выше примере будет выглядеть следующим образом:

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

Одна дополнительная вещь: два списка изначально являются двумя IQueryables;Я просто делаю ToList (), чтобы иметь их в виде списков.

Как получить правильный результат, используя списки (или Iqueryables, если ToList () не нужен?

Спасибо взаранее!

Ответы [ 3 ]

2 голосов
/ 18 марта 2019

Я думаю, что получил то, что ты хочешь - ты хочешь не показывать ни одного идентификатора дважды. Так что, если в поле «родитель» используется какой-либо «родитель», вы не хотите его использовать в результате?

в этом случае вы можете сделать это:

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

Часть Where исключает все элементы, которые используются в качестве родителей в List2. И, с Union (исключая дубликаты), он объединяет List2. ToList () может быть необязательным, в зависимости от того, что вы будете делать с ним дальше.

РЕДАКТИРОВАТЬ: Изменена форма Concat на Union.

0 голосов
/ 18 марта 2019

Вы можете использовать System.Linq методы расширения Union (чтобы получить объединение двух списков) вместе с Where и All, чтобы отфильтровать элементы, которые вы не хотите включать в первый список:

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

Но учтите, что Union будет использовать метод класса Equals, чтобы определить, совпадают ли два элемента (который по умолчанию является эталонным сравнением), поэтому вам придется переопределить Equalsи GetHashCode для удаления дубликатов (где дубликат будет определен вами, в этом случае, я думаю, будет определено, где совпадают свойства 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...");
    }
}
0 голосов
/ 18 марта 2019

Вы можете попытаться найти первое совпадение ParentId из List2 во время итерации List1 и добавить в зависимости от того, был ли он найден:

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