Как добавить элемент uniqe из списка в ObservableCollection с помощью Linq

У меня есть вопрос о проверке, существует ли объект в одном списке в другом, и если не добавить их во второй список, все с помощью Linq. На самом деле у меня есть две петли с одним условием:

 foreach (var p in seznamVlaku.Select(s => s.ProjizdejiciStanicemi)) {
            foreach (var l in p) {
                if (_nodes.Any(a => a.ID != l.Key.ID)){
                    _nodes.Add(new Node() {Name = l.Key.Jmeno, ID = l.Key.ID, X = l.Key.X, Y = l.Key.Y });
                }
            }
        }

Можно ли сделать это быстрее с помощью запроса Linq?

Этот _nodes.Any(a => a.ID != l.Key.ID) означает «если есть узел, который имеет другой идентификатор, чем _nodes.Add(...)». Это опечатка? Разве не должно быть: !_nodes.Any(a => a.ID == l.Key.ID)?

Fabjan 09.08.2018 15:51

Вы можете использовать IEnumerable.Except() для фильтрации элементов, которые существуют в другом списке. NewList.AddRange(OriginalList.Except(TheOtherList));

Bradley Uffner 09.08.2018 15:55

@BradleyUffner, для которого потребуется настраиваемый компаратор проверки на равенство, или ExceptBy от MoreLinq.

René Vogt 09.08.2018 15:56

Фабиан, ты прав :)

PadloctCZ 09.08.2018 15:56

_nodes - это коллекция List<T>?

Fabjan 09.08.2018 16:12
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
5
72
3

Ответы 3

Я не думаю, что есть много способов Быстрее, вам нужно проверить, существует ли l уже в _nodes, и это для каждого l. Если бы вы могли оптимизировать это на более высоком уровне, я не могу сказать, не зная, что это делает.

Если вам просто нужен более короткий оператор LINQ, вы можете использовать SelectMany:

foreach(var l in sznamVlaku.SelectMany(s => s.ProjizdejiciStanicemi)
                           .Where(x => _nodes.All(a => a.ID != x.Key.ID)))
    _nodes.Add(new Node() {Name = l.Key.Jmeno, ID = l.Key.ID, X = l.Key.X, Y = l.Key.Y });

Обратите внимание, что я использовал All вместо Any, потому что вы хотите найти все l, где узлы все имеют другой ID.

  1. Вам не нужно два foreach. Вместо этого используйте SelectMany.

Ваш пример:

foreach (var p in seznamVlaku.Select(s => s.ProjizdejiciStanicemi))
{
    foreach (var l in p)
    {
    }
}

Мы можем написать подобное, и будет то же самое:

foreach (var node in seznamVlaku.SelectMany(list => list.ProjizdejiciStanicemi))
{
}
  1. Вы можете добавить условие (существующий элемент) в конвейер запроса linq

Код:

foreach (var node in seznamVlaku
    .SelectMany(list => list.ProjizdejiciStanicemi)
    .Where(item => nodes
        .Exists(node => node.ID != item.ID)))
{
    _nodes.Add(new Node() {Name = node.Key.Jmeno, ID = node.Key.ID, X = node.Key.X, Y = node.Key.Y });
}

Следующий код должен быть значительно быстрее, потому что он использует хеширование вместо вложенных циклов:

// build a HashSet of your key's type (I'm assuming integers here) containing all your current elements' keys in the _nodes ObservableCollection
HashSet<int> hashSet = new HashSet<int>(_nodes.Select(n => n.ID));

foreach (var l in seznamVlaku.SelectMany(s => s.ProjizdejiciStanicemi)) {
    // if you can add the element's ID to the HashSet it hasn't been added before
    if (hashSet.Add(l.Key.ID)) {
        _nodes.Add(new Node() {Name = l.Key.Jmeno, ID = l.Key.ID, X = l.Key.X, Y = l.Key.Y });
    }
}

Другие вопросы по теме