2013-11-25 1 views
2

Как удалить элементы из IEnumerable, соответствующие определенным критериям?Как удалить элементы в IEnumerable <MyClass>?

RemoveAll() не применяется.

+0

У вас есть определение класса и критерии? –

+0

Возможный дубликат [Удалить элементы из IEnumerable ] (http://stackoverflow.com/questions/3185975/remove-items-from-ienumerablet) –

ответ

11

Вы не можете; IEnumerable как интерфейс не поддерживает удаление.

Если ваш экземпляр IEnumerable фактически относится к типу, который поддерживает удаление (например, List<T>), то вы можете использовать его для этого типа и использовать метод Remove.

В качестве альтернативы вы можете скопировать элементы в другой IEnumerable на основе ваших критериев, или вы можете использовать ленивую-оценивали запрос (например, с .Where Linq), чтобы фильтровать IEnumerable на лету. Однако ни одно из них не повлияет на ваш оригинальный контейнер.

+0

В моем случае код выполнял '.Aggregate' в' IEnumerable'. Я добавил фильтр «.Where», как предположил Дэн, например. 'Foo.Where (условие) .Aggregate (выражение)'. Оно работало завораживающе. –

1

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

var filtered = myCollection.Where(x => x.SomeProp != SomValue); 

Другим вариантом было бы использовать Where для создания нового IEnumerable<T> со ссылками на объекты, которые вы хотите удалить, а затем передать, что к Remove вызова на оригинальной коллекции. Конечно, это на самом деле потребляет больше ресурсов.

+0

Что такое _this_ в _This будет производить новую коллекцию_? –

+0

@AustinSalonen с использованием 'Where' будет выпускать новую коллекцию. Запросы LINQ обычно не изменяют существующую коллекцию, вместо этого они создают новый «IEnumerable » с набором результатов. – evanmcdonnal

0

Элементы не могут быть удалены с IEnumerable<T>. От documentation:

Выдает перечислитель, который поддерживает простую итерацию по набору определенного типа.

1

Вы не можете удалить предметы с сайта IEnumerable<T>. Вы можете удалить элементы из ICollection<T> или фильтровать элементы из IEnumerable<T>.

// filtering example; does not modify oldEnumerable itself 
var filteredEnumerable = oldEnumerable.Where(...); 
// removing example 
var coll = (ICollection<MyClass>)oldEnumerable; 
coll.Remove(item); 
1

Вы не удалить элементы из IEnumerable. Это невозможно. Это всего лишь последовательность предметов. Вы можете удалить элементы из некоторого базового источника, который генерирует последовательности, например, если IEnumerable основан на списке, вы можете удалить элементы из этого списка.

Другой вариант, который у вас есть, - создать новую последовательность, основанную на этом, которая никогда не отображает данные. Вы можете сделать это с помощью Where, но важно понимать, что это не удаление элементов, а выбор для отображения элементов, основанных на определенном состоянии.

+0

Это не невозможно. @TimS. ссылался на него в своем ответе. Также см. Мой ответ на другой вопрос о подобной теме на http://stackoverflow.com/a/15858794/425871 – Steve

+0

@Steve Как я указал * в своем ответе, вы можете удалить элементы из некоторой коллекции, которая является базовым источником данных для 'IEnumerable'. Это все еще не удаляет элементы из 'IEnumerable', но это удаление элементов из базового источника данных. – Servy

+1

Ваше право - я не читал ваш ответ достаточно близко :) – Steve

1

Как уже было сказано, вы не можете удалить из IEnumerable, потому что это не то, что описывает интерфейс. Рассмотрим следующий пример:

public IEnumerable<string> GetSomeStrings() 
{ 
    yield return "FirstString"; 
    yield return "Another string"; 
} 

Очевидно, что удаление элемента из этого IEnumerable не то, что вы можете разумно сделать, вместо этого вы должны были бы сделать новое перечисление без них вы не хотите.

yield keywork предоставляет другие примеры, например, вы можете иметь бесконечные списки:

public IEnumberable<int> GetPowersOf2() 
{ 
    int value = 1; 
    while(true) 
    { 
     yield return value; 
     value = value * 2; 
    } 
} 
0

Вы можете бросить его и использовать List<T>.RemoveAll(Predicate<T> match) это именно то, что вам нужно.

-1

Как о попытке Enumerable.Empty т.е.

T obj = new T(); 
IEnumerable<T> myVar = new T[]{obj} //Now myVar has an element 
myVar = Enumerable.Empty<T>();  //Now myVar is empty 
+1

Назначение нового значения переменной не повлияет на исходное значение. – Servy

0

Это, как я делаю,

IEnumerable<T> myVar=getSomeData(); // Assume mayVar holds some data 

myVar=myVar.Where(d=>d.Id>10); // thats all, i want data with Id>10 only 
Смежные вопросы