Удаление N элементов из списка условно

Я писал некоторый элемент управления ASP.NET, когда подошел к сценарию, в котором мне нужно было удалять элементы из списка, только когда они соответствовали определенному условию.

RemoveAllМетод общего Listкласса делает хорошую работу, но удаляет все элементы , которые соответствуют условию, указанному предикат.

Что если я хочу удалить только определенное количество элементов, указывающих условие? Как вы думаете, это лучший способ сделать это?

19.08.2008 15:57:51
6 ОТВЕТОВ
РЕШЕНИЕ

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

int limit = 30; // Suppose you want to remove 30 items at most
list.RemoveAll(item => ShouldIRemoveThis(item) && limit-- > 0);
8
19.08.2008 16:19:51
Лямбда-выражения так кевел.
Cheeso 24.02.2009 06:04:25

Если в методе не указан параметр «limit» (а он этого не делает), лучшим вариантом будет использовать простой цикл, который удаляет совпадающие элементы, прерываясь, когда ваш увеличенный «счетчик совпадений» достигает вашего предела.

Это почти то же самое, что внутренняя функция работает в любом случае, но более оптимизированным способом.

1
19.08.2008 16:13:05

В рамках 3.5 метод RemoveAll принимает предикат в качестве параметра. Таким образом, вы можете использовать

list.RemoveAll(item => ShouldIRemoveThis(item));

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

1
19.08.2008 16:00:46

Вы можете использовать LINQ? Если это так, вы можете просто использовать метод .Take () и указать, сколько записей вы хотите (может быть, всего - N).

0
19.08.2008 16:01:11

Анонимные делегаты полезны здесь. Простой пример удаления первого ограничения четных чисел из списка.

List<int> myList = new List<int>;
for (int i = 0; i < 20; i++) myList.add(i);

int total = 0;
int limit = 5;
myList.RemoveAll(delegate(int i) { if (i % 2 == 0 && total < limit) { total++; return true; } return false; });

myList.ForEach(i => Console.Write(i + " "));

Дает 1 3 5 7 9 10 11 12 13 14 15 16 17 18 19, как мы хотим. Достаточно легко обернуть это в функцию, подходящую для использования в качестве лямбда-выражения, взяв реальный тест в качестве параметра.

0
19.08.2008 16:16:08

@buyutec

Вместо того

list.RemoveAll(item => ShouldIRemoveThis(item));

вы можете использовать:

list.RemoveAll(ShouldIRemoveThis);

Лямбда имеет ту же сигнатуру, что и метод, поэтому они эквивалентны, поэтому вы можете просто передать метод напрямую.

5
19.08.2008 16:18:23