2010-02-15 39 views
5

En primer lugar, es muy posible que me esté acercando a mi problema de la manera incorrecta, en cuyo caso aceptaría con gusto las alternativas.Cómo restar una lista genérica de otra en C# 2.0

Lo que estoy tratando de lograr es detectar qué unidad se creó después de que se conectó un dispositivo USB a una computadora.

Aquí es el flujo de trabajo simplificado:

// Get list of removable drives before user connects the USB cable 
List<string> listRemovableDrivesBefore = GetRemovableDriveList(); 

// Tell user to connect USB cable 
... 

// Start listening for a connection of a USB device 
... 

// Loop until device is connected or time runs out 
do 
{ 
    ... 
} while 

// Get list of removable drives after USB device is connected 
List<string> listRemovableDrivesAfter = GetRemovableDriveList(); 

// Find out which drive was created after USB has been connected 
??? 

GetRemovableDriveList devuelve una lista de cadenas de las letras de las unidades extraíbles. Mi idea era obtener una lista de unidades extraíbles antes de el dispositivo está conectado, y otra lista después de está conectado, y que al eliminar el contenido de la primera lista de la segunda, me quedaría con unidades que solo estaban conectados (normalmente solo uno).

Pero no puedo encontrar una manera simple de "restar" una lista de otra. Cualquiera podría sugerir una solución, o incluso una mejor manera de lograr lo que estoy tratando de hacer.

Nota: el proyecto se dirige a .NET framework 2.0, por lo que no es posible LINQ.

Gracias!

Respuesta

1

Para un pequeño número de elementos a continuación, un bucle foreach con una llamada Contains debe hacer el truco:

List<string> listRemovableDrivesBefore = GetRemovableDriveList(); 
// ... 
List<string> listRemovableDrivesAfter = GetRemovableDriveList(); 

List<string> addedDrives = new List<string>(); 
foreach (string s in listRemovableDrivesAfter) 
{ 
    if (!listRemovableDrivesBefore.Contains(s)) 
     addedDrives.Add(s); 
} 

Si la colección tiene muchos elementos, entonces podría hacer que las operaciones de búsqueda más eficiente mediante el uso de un Dictionary<K,V> en lugar de a List<T>. (Idealmente utilizaría un HashSet<T>, pero eso no está disponible en la versión 2 del framework.)

+0

Elegí esta respuesta porque necesitaba algo de una sola vez. Si hubiera necesitado hacer esto repetidamente y en diferentes lugares, probablemente habría implementado el Resta de la respuesta de Lee. – Fueled

3

Una forma general de hacerlo sería agregar todos los elementos de la colección fuente a un diccionario y luego eliminar los elementos en la otra colección:

public static IEnumerable<T> Subtract<T>(IEnumerable<T> source, IEnumerable<T> other) 
{ 
    return Subtract(source, other, EqualityComparer<T>.Default); 
} 

public static IEnumerable<T> Subtract<T>(IEnumerable<T> source, IEnumerable<T> other, IEqualityComparer<T> comp) 
{ 
    Dictionary<T, object> dict = new Dictionary<T, object>(comp); 
    foreach(T item in source) 
    { 
     dict[item] = null; 
    } 

    foreach(T item in other) 
    { 
     dict.Remove(item); 
    } 

    return dict.Keys; 
} 
+0

Una solución eficiente, pero el método es mal nombrado. No devuelve la intersección de las dos secuencias. – LukeH

+0

En mi opinión, ambas respuestas son válidas, pero debido a mis requisitos, elegí la manera fácil. – Fueled

1

usted puede trabajar con LINQ del método de extensión Reste y Insersect, igual que lo hace con juego de matemáticas.

A = Original.

B = Después.

A - (A Intersect B) = retirado del original de B - (A insersect B) = nuevo

var intersectan = A.Intersect (B);

var removed = A.Sustraer (intersecar); var new = B.Substract (intersect)

Espero que esto funcione para usted.

+3

Linq no tiene un método llamado Restar (o Substrato). Creo que te refieres a ['Except'] (http://msdn.microsoft.com/en-us/library/bb300779.aspx). – JLRishe

Cuestiones relacionadas