2009-06-22 23 views
19

¿Cuál es la forma preferible para transferir algunos elementos (no todos) de una lista a otra?¿Cómo muevo los artículos de una lista a otra lista en C#?

Lo que estoy haciendo es el siguiente:

var selected = from item in items 
       where item.something > 10 
       select item; 

otherList.AddRange(selected); 

items.RemoveAll(item => selected.Contains(item)); 

Con el fin de tener el más rápido mejor código/no existe, hay una manera mejor?

+0

Me gustaría ver usando el método ParaCada en la Lista de manejar esto. Además, es probable que desee estandarizar el uso de la sintaxis de la consulta o la sintaxis del método, no ambos. –

Respuesta

13

Me gustaría probar la respuesta de @ Mehrdad, y tal vez la prueba contra éste también ...

var selected = items.Where(item => item.Something > 10).ToList(); 
selected.ForEach(item => items.Remove(item)); 
otherList.AddRange(selected); 
+0

¡Simple! respuesta aceptada –

9

sugiero:

var selected = items.Where(item => item.Something > 10).ToList(); 
items = items.Except(selected).ToList(); 
otherList.AddRange(selected); 
+0

Esto es definitivamente más rápido que la respuesta aceptada de 'ForEach' –

6

Eso es bastante mala actuación sabia - que en realidad enumera una consulta n veces (para n elementos en items). Sería mejor si construyes (por ejemplo) un HashSet<T> de los elementos para manipular.

Para dar un ejemplo sencillo simplemente con int valores:

var items = new List<int> { 1, 2, 3, 4, 5, 6 }; 
    var otherList = new List<int>(); 
    var selected = new HashSet<int>(items.Where(
     item => item > 3)); 
    otherList.AddRange(selected); 
    items.RemoveAll(selected.Contains); 
+0

No estoy seguro de si veo correctamente cómo la consulta se enumerará n veces ... ¿Es por el uso de la consulta" seleccionada "en AddRange y RemoveAll ? En el peor de los casos, pensé que la enumeración iría solo dos veces ... –

+2

"seleccionado" es un

+0

¡Oh! Ya lo veo. Tienes razón. –

6

RemoveAll pasa a través cada elemento y enumera todos los valores de su lista seleccionada cada vez. Esto tomará más tiempo de lo que debería ...

lo que he hecho es poner la condición directamente en el parámetro RemoveAll:

items.RemoveAll(item => item.something > 10); 

Si usted hace esto y no cambia el resto de su código habría duplicación de código, lo cual no es bueno. Yo haría lo siguiente para evitarlo:

Func<ItemType, bool> selectedCondition = (item => item.something > 10); 

otherList.AddRange(items.Where(selectedCondition)); 

items.RemoveAll(new Predicate<ItemType>(selectedCondition)); 
+0

+1. Este es el mejor método (a menos que la condición Where sea mucho más compleja que la comprobación de la igualdad del elemento). Solo asegúrate de no cambiar la colección entre las llamadas a métodos. Puede perder elementos. –

+0

Por cierto, no puedes usar 'var' con un lambda (incluso si arreglas la sintaxis rota). –

+0

Creo que está arreglado ahora. ¿Había alguna otra sintaxis "rota" además de mi punto y coma faltante? –

1

¿Qué tal una partición:

int[] items = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; 
var partition = items.ToLookup(x => x > 5); 
var part1 = partition[true]; 
var part2 = partition[false]; 
Cuestiones relacionadas