У меня есть вопрос о проверке, существует ли объект в одном списке в другом, и если не добавить их во второй список, все с помощью 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?
Вы можете использовать IEnumerable.Except()
для фильтрации элементов, которые существуют в другом списке. NewList.AddRange(OriginalList.Except(TheOtherList));
@BradleyUffner, для которого потребуется настраиваемый компаратор проверки на равенство, или ExceptBy
от MoreLinq.
Фабиан, ты прав :)
_nodes
- это коллекция List<T>
?
Я не думаю, что есть много способов Быстрее, вам нужно проверить, существует ли 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
.
Ваш пример:
foreach (var p in seznamVlaku.Select(s => s.ProjizdejiciStanicemi))
{
foreach (var l in p)
{
}
}
Мы можем написать подобное, и будет то же самое:
foreach (var node in seznamVlaku.SelectMany(list => list.ProjizdejiciStanicemi))
{
}
Код:
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 });
}
}
Этот
_nodes.Any(a => a.ID != l.Key.ID)
означает «если есть узел, который имеет другой идентификатор, чем_nodes.Add(...)
». Это опечатка? Разве не должно быть:!_nodes.Any(a => a.ID == l.Key.ID)
?