2012-04-16 1 views
7

Это самый простой способ удалить элементы, соответствующие определенному условию из списка, а затем получить эти элементы.LINQ: RemoveAll и удалить элементы

я могу думать несколько способов, я не знаю, что является лучшим выбором:

var subList = list.Where(x => x.Condition); 
list.RemoveAll(x => x.Condition); 

или

var subList = list.Where(x => x.Condition); 
list.RemoveAll(x => subList.Contains(x)); 

Является ли какой-либо из этого один из лучших способов? Если да, то какой? Если это не так, как мне это сделать?

ответ

4

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

var sublist = list.Where(x => x.Condition).ToArray(); 
list.RemoveAll(x => x.Condition); 

Второй пример - O (n^2) без всякой причины, а последнее отлично, но менее читаемо.

Редактировать: теперь, когда я перечитаю ваш последний пример, обратите внимание, что как только он написан прямо сейчас, он будет вынимать каждый другой элемент. Вам не хватает проверки состояния, и строка удаления должна быть на самом деле равна list.RemoveAt(i--);, потому что после удаления i+1-й элемент становится удаляемым, а когда вы увеличиваете скорость i, вы пропускаете его.

+0

Это на самом деле O (N^3), но я предполагаю, что отсутствие материализации просто поскользнулся ваш mind;) – Blindy

+0

Удалены ли элементы (как я их написал) из сублиста со второй инструкцией? : O – Diego

+0

Er, который вы никогда не удаляете из 'sublist', и не собираетесь, если я его правильно прочитаю. – Blindy

2

Мне нравится использовать подход к функциональному программированию (только делайте новые вещи, не изменяйте существующие вещи). Одним из преимуществ ToLookup является то, что вы можете обрабатывать более двухстороннее разделение элементов.

ILookup<bool, Customer> lookup = list.ToLookup(x => x.Condition); 
List<Customer> sublist = lookup[true].ToList(); 
list = lookup[false].ToList(); 

Или, если вам нужно изменить исходный экземпляр ...

list.Clear(); 
list.AddRange(lookup[false]); 
+0

Я думаю, что это очень сложно (и почти без знания, я думаю, что это не очень высокая производительность). Имеет ли это преимущество? – Diego

+0

Условие оценивается ровно один раз за элемент. Экземпляр списка не изменяется, что может быть большим преимуществом, если этот экземпляр списка разделяется между потоками. –

+0

Это довольно гениальная идея. – Timo