2012-01-26 10 views
6

Ho un elenco dalla libreria di raccolte .NET e voglio rimuovere un singolo elemento. Purtroppo, non riesco a trovarlo confrontando direttamente con un altro oggetto.Rimozione elemento dall'elenco con predicato

Temo che l'utilizzo di FindIndex e RemoveAt causerà più traversamenti dell'elenco.

Non so come utilizzare gli Enumeratori per rimuovere elementi, altrimenti avrebbe potuto funzionare.

RemoveAll fa ciò di cui ho bisogno, ma non si fermerà dopo che un elemento è stato trovato.

Idee?

+0

Potrebbe mostrare qualche codice di esempio? –

+0

Le domande sono contrassegnate con 'linked-list' ma la descrizione suggerisce' Elenco '. Cos'è questo? – Ani

+0

Che tipo è la tua lista? – Strillo

risposta

1

EDIT: Ora l'OP è cambiato per usare un LinkedList<T>, è facile dare una risposta che solo itera per quanto deve:

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

Sto cercando solo di rimuovere un singolo elemento. – Steinbitglis

+0

@Steinbitglis: ci saranno più valori che corrispondono al predicato? E che tipo di lista stai usando? –

+0

@Steinbitglis: Modificato per mostrare come è possibile utilizzare un effetto collaterale per utilizzare 'RemoveAll'. –

2

Se si desidera rimuovere solo il primo elemento che corrisponde un predicato è possibile utilizzare il seguente (esempio):

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

dove (x => x = 10) è ovviamente il vostro predicato per la corrispondenza degli oggetti.

+0

Ciò richiede che l'elenco sia enumerato due volte. Una volta per trovare un oggetto corrispondente. Una volta per trovare di nuovo questo elemento in 'Rimuovi'. –

+1

È vero, usare RemoveAt è più efficiente. – Strillo

10

List<T> ha un metodo FindIndex che accetta un predicato

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

Rimuove prima parola che inizia con "x". Si assume che words sia un List<string> in questo esempio.

+0

Se la lista ha una ricerca dell'indice a tempo costante, penso che sarà ok. Ero preoccupato che RemoveAt avrebbe anche attraversato la lista. – Steinbitglis

+1

@Steinbitglis: È un'operazione O (n), perché deve copiare tutto. In realtà * volevi * un elenco collegato? –

+0

Beh, ho pochissimi elementi, che continuano ad andare e venire.Penso che almeno l'hashtable sarebbe stupido. Non vedo alcun problema con le liste collegate, a parte questa ottimizzazione apparentemente banale che non riesco a capire. – Steinbitglis