tags:

views:

96

answers:

5

Hey all,

I'm trying to locate all the keys in one Dictionary that are not in another Dictionary. Obviously, I can do this using a nested loop, but I'm trying to learn LINQ at the moment and I was wondering if I might use it to accomplish this task?

Here's what I have so far:

Dictionary<string, List<string>> DBtables = this.CollectTableListings();
var generic = from Dictionary<string,List<string>> tab
              in DBtables
              where !_tables.ContainsKey(???)
              select tab;

Any idea what should go in place of the question marks (or perhaps instead of the entire where clause)?

Thanks, Matt

+9  A: 

You can do:

var resultKeys = DBTables.Keys.Except( _tables.Keys );

The Except() method is essentially the same as the minus operations in SQL - it returns all items from the first collection excluding those in the second. Since dictionaries expose their keys, you can compute their difference that way.

The Except() operator uses the default equality for the type, but there is also an overload which allows you to specify your own IEqualityComparer to override the semantics of how to compare values. In your example, you probably don't need that - but it's nice to know it there.

LBushkin
Please note, `Except()` Returns **Distinct** results. While that may be desired in this example, it's worth noting for use in other implementations.
Aren
@Aren B: True, but in the case of a `Dictionary<>`, they keys are already guaranteed to be distinct.
LBushkin
I know, That's why I stated that this example it's desired. But someone may stumble upon this thread looking for a *List Subtraction* and think that `Except()` may solve their problems. Hence why I said it was worth noting.
Aren
If performance is a concern, I'd opt for @Aren B's answer.
Marc
+2  A: 
Dictionary<string, List<string>> dictOne = ...
Dictionary<string, List<string>> dictTwo = ...

var missingKeys = dictOne.Keys.Where(x => !dictTwo.ContainsKey(x));
Aren
+1  A: 
Dictionary<string, List<string>> dictionary = this.CollectTableListings();
Dictionary<string, List<string>> otherDictionary = getOtherTable();

var keys = from key in dictionary.Keys
           where !otherDictionary.Keys.Contains(key)
           select key;

(But LBuskin's answer is much better)

Ian Henry
A: 

Hi,

have a look at the Except extension method. HTH.

andyp
A: 

If you wanted to use query syntax I would do something akin to below:

var keys = from d1 in dictionary1
           select d1.Key;
var items = from d2 in dictionary2
            where d2.Key in keys
            select d2;
foreach(var item in items)
{
}
Kirk