Удаление элемента из списка с помощью предиката - PullRequest
8 голосов
/ 26 января 2012

У меня есть список из библиотеки коллекций .NET, и я хочу удалить один элемент.К сожалению, я не могу найти его, сравнивая напрямую с другим объектом.

Боюсь, что использование FindIndex и RemoveAt вызовет многократные обходы списка.

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

RemoveAll делает то, что мне нужно, но не остановится после того, как найден один элемент.

Идеи?

Ответы [ 4 ]

12 голосов
/ 26 января 2012

List<T> имеет метод FindIndex, который принимает предикат

int index = words.FindIndex(s => s.StartsWith("x"));
words.RemoveAt(index);

Удаляет первое слово, начинающееся с "x". words в этом примере предполагается List<string>.

2 голосов
/ 26 января 2012

Если вы хотите удалить только первый элемент, который соответствует предикату, вы можете использовать следующий (пример):

List<int> list = new List<int>();
list.Remove(list.FirstOrDefault(x => x = 10));

, где (x => x = 10), очевидно, ваш предикат для сопоставленияобъекты.

1 голос
/ 26 января 2012

РЕДАКТИРОВАТЬ: теперь OP изменился на использование LinkedList<T>, легко дать ответ, который повторяется только настолько, насколько это необходимо:

public static void RemoveFirst<T>(LinkedList<T> list, Predicate<T> predicate)
{
    var node = list.First;
    while (node != null)
    {
        if (predicate(node.Value))
        {
            list.Remove(node);
            return;
        }
        node = node.Next;
    }
}
0 голосов
/ 03 мая 2018

На случай, если кому-то понадобится то же самое, но за IList<T> (вдохновлено ответом Стрилло, но более эффективно)

public bool Remove(this IList<T> list, Predicate<T> predicate)
{
    for(int i = 0; i < list.Count; i++)
    {
        if(predicate(list[i]))
        {
            list.RemoveAt(i);
            return true;
        }                   
    }   

    return false;
}
...