Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to subtract one generic list from another in C#2.0

First of all, it very well could be that I'm approaching my problem the wrong way, in which case I'd gladly accept alternatives.

What I'm trying to achieve is to detect which drive was created after a USB device has been connected to a computer.

Here is the simplified workflow:

// 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 returns a list of strings of the removable drive letters. My idea was to get a list of removable drives before the device is connected, and another list after it is connected, and that by removing the contents of the first list from the second, I would be left with drives that were just connected (normally only one).

But I can't find a simple way of "subtracting" one list from another. Anyone could suggest a solution, or even a better way of achieving what I'm trying to do.

Note: project is targeting the .NET framework 2.0, so no LINQ possible.

Thanks!

like image 298
Fueled Avatar asked Feb 15 '10 14:02

Fueled


3 Answers

A general way to do this would be to add all the items from the source collection to a dictionary and then remove items in the other collection:

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;
}
like image 130
Lee Avatar answered Nov 03 '22 08:11

Lee


For a small number of elements then a foreach loop with a Contains call should do the trick:

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);
}

If the collection has many elements then you could make the lookups more efficient by using a Dictionary<K,V> rather than a List<T>. (Ideally you'd use a HashSet<T>, but that's not available in version 2 of the framework.)

like image 25
LukeH Avatar answered Nov 03 '22 08:11

LukeH


You can work with Linq extension method's Subtract and Insersect, same as you do with math set.

A = Original.

B = After.

A - (A Intersect B) = removed from original B - (A insersect B) = new

var intersect = A.Intersect(B);

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

Hope this works for you.

like image 1
Andrés Falcón Avatar answered Nov 03 '22 07:11

Andrés Falcón