tags:

views:

56

answers:

2

How do I insertsect two lists of KeyValuePairs based on their keys? I have tried:

List<KeyValuePair<string, string>> listA = new List<KeyValuePair<string, string>>();
List<KeyValuePair<string, string>> listB = new List<KeyValuePair<string, string>>();
...
var result = listA.Intersect(listB);

Which expectedly doesn't work. Do I need to write my own comparer based on the key or is there a easy way using LINQ/Lambda?

Thanks!

+3  A: 

I suspect you would indeed have to write your own comparer - at least to use Intersect.

You could use ProjectionEqualityComparer from MiscUtil to make this easy though:

// Ick what a mouthful
var comparer = ProjectionEqualityComparer<KeyValuePair<string, string>>.Create
       (x => x.Key);

var result = listA.Intersect(listB, comparer);

If the keys are unique within each list, another option would be a join:

var commonPairs = from pairA in listA
                  join pairB in listB on pairA.Key equals pairB.Key
                  select new { pairA, pairB };
Jon Skeet
It's close to what I need, but I can't be sure the keys will be unique. (And I would rather not reference another assembly.)
ehcanadian
@Alex: The link was broken very briefly, but I fixed it afterwards. It should be fine.
Jon Skeet
@Jon - forgot to say thanks!
ehcanadian
+2  A: 
var keysFromB = new HashSet<string>(listB.Select(x => x.Key));
var result = listA.Where(x => keysFromB.Remove(x.Key));

Note that this code mimics the behaviour of Intersect by using the Remove method. This means that both sequences are treated as sets: if there are multiple items with the same key in listA then result will only contain one of those items. If you don't want this behaviour then use the Contains method instead of Remove.

LukeH
Perfect - Thank you!
ehcanadian