1

What do you call this method, (is it available in .net?)

var list1 = new List<int>() { 1, 2, 2, 3, 4 };
var list2 = new List<int>() { 1, 2, 3};
var results = list1.diff(list2);

results:
{ 2, 4 }
Brian Rasmussen
  • 114,645
  • 34
  • 221
  • 317
kobi7
  • 969
  • 1
  • 7
  • 15

4 Answers4

2

The closest thing built in is the Except LINQ operator.

Produces the set difference of two sequences.

Though with your example it will result in:

{ 4 }

I don't believe there is a direct analogue to what you want.

Oded
  • 489,969
  • 99
  • 883
  • 1,009
2

You actually need a multiset implementation. Although there is no multiset out of the box in BCL, there are some ideas here and in the linked question.

Or you can actually implement one by yourself, it's not so complicated:

class Multiset<K> // maybe implement IEnumerable?
{
    Dictionary<K, int> arities = new Dictionary<K, int>();
    ...
    Multiset<K> Except(Multiset<K> other)
    {
        foreach (var k in arities.keys)
        {
            int arity = arities[k];
            if (other.Contains(k))
                arity -= other.Arity(k);
            if (arity > 0)
                result.Add(k, arity);
        }
        return result;
    }
}
Community
  • 1
  • 1
Vlad
  • 35,022
  • 6
  • 77
  • 199
1

This exactly return what you want, You can refactor it in a Extension Method:

var results = list1.GroupBy(p => p).Select(p => new { item = p.Key, count = p.Count() })
                .Concat(list2.GroupBy(p => p).Select(p => new { item = p.Key, count = -p.Count() }))
                .GroupBy(p => p.item).Select(p => new { item = p.Key, count = p.Sum(q => q.count) })
                .Where(p => p.count > 0)
                .SelectMany(p => Enumerable.Repeat(p.item, p.count));
Reza ArabQaeni
  • 4,848
  • 27
  • 46
0

Like this: (see oded's post for a linq to msdn)

int[] numbersA = { 0, 2, 4, 5, 6, 8, 9 }; 
int[] numbersB = { 1, 3, 5, 7, 8 }; 

IEnumerable<int> aOnlyNumbers = numbersA.Except(numbersB); 
albertjan
  • 7,739
  • 6
  • 44
  • 74