patterncsharpMinor
Removing exact instances of elements in one list from another
Viewed 0 times
exactelementsinstancesremovingoneanotherlistfrom
Problem
Basically, here's the problem statement:
Given an
Let's take an example:
Exception list:
Source list:
Result:
Code:
Usage:
Output:
Given an
IEnumerable source and an IEnumerable exceptions, return an IEnumerable result which contains all of source, without exceptions, only omitting exact instances of a value. I.e.: if a value appears twice in source, but once in exceptions, then result will have that value exactly one time.Let's take an example:
Exception list:
{ 2, 2, 3, 4, 5}Source list:
{ 2, 2, 2, 6 }Result:
{ 2, 6 }Code:
public static IEnumerable ExceptExact(this IEnumerable source, IEnumerable exceptions)
{
var tExceptions = new List();
tExceptions.AddRange(exceptions);
var result = new List();
foreach (var el in source)
{
if (tExceptions.Contains(el))
{
tExceptions.RemoveAt(tExceptions.IndexOf(el));
}
else
{
result.Add(el);
}
}
return result;
}Usage:
var a = new List { 2, 3, 5, 4, 2 };
var b = new List { 2, 2, 2, 6 };
var c = b.ExceptExact(a);
var d = a.ExceptExact(b);
Console.WriteLine("A: { " + string.Join(", ", a) + " }");
Console.WriteLine("B: { " + string.Join(", ", b) + " }");
Console.WriteLine("C: { " + string.Join(", ", c) + " }");
Console.WriteLine("D: { " + string.Join(", ", d) + " }");Output:
A: { 2, 3, 5, 4, 2 }
B: { 2, 2, 2, 6 }
C: { 2, 6 }
D: { 3, 5, 4 }Solution
Additional to the valid point from Rick Davin:
1) You can drop the
2) You could use yield to get rid of the additional list
After taking a look to MSDN (List.Remove), I figured out that there is even a simpler way:
Removes the first occurrence of a specific object from the List.
Returns true if item is successfully removed; otherwise, false.This method
also returns false if item was not found in the List.
1) You can drop the
Contains because IndexOf returns -1 if the item is not contained.2) You could use yield to get rid of the additional list
public static IEnumerable ExceptExact(this IEnumerable source, IEnumerable exceptions)
{
var tExceptions = exceptions.ToList();
foreach (var el in source)
{
var index = tExceptions.IndexOf(el);
if (index >= 0)
{
tExceptions.RemoveAt(index);
continue;
}
yield return el;
}
}After taking a look to MSDN (List.Remove), I figured out that there is even a simpler way:
Removes the first occurrence of a specific object from the List.
Returns true if item is successfully removed; otherwise, false.This method
also returns false if item was not found in the List.
public static IEnumerable ExceptExact(this IEnumerable source, IEnumerable exceptions)
{
var tExceptions = exceptions.ToList();
return source.Where(el => !tExceptions.Remove(el));
}Code Snippets
public static IEnumerable<T> ExceptExact<T>(this IEnumerable<T> source, IEnumerable<T> exceptions)
{
var tExceptions = exceptions.ToList();
foreach (var el in source)
{
var index = tExceptions.IndexOf(el);
if (index >= 0)
{
tExceptions.RemoveAt(index);
continue;
}
yield return el;
}
}public static IEnumerable<T> ExceptExact<T>(this IEnumerable<T> source, IEnumerable<T> exceptions)
{
var tExceptions = exceptions.ToList();
return source.Where(el => !tExceptions.Remove(el));
}Context
StackExchange Code Review Q#134413, answer score: 8
Revisions (0)
No revisions yet.