c# dictionaries intersect
Asked Answered
R

4

18

I have a question about Linq / Lambda and the following issue:

I have two dictionaries, primary and secondary... These two dictionaries are defined as Key=string, Value=int. I need to trim down the primary dictionary if the KEYS intersect with secondary dictionary.

i.e.:

primaryDict = ["thing1", 33] ["thing2", 24] ["thing3", 21] ["thing4", 17] ["thing5", 12]

secondaryDict = ["thing1", 22] ["thing3", 20] ["thing4", 19] ["thing7", 17] ["thing9", 10]

resultDict = ["thing1", 33] ["thing3", 21] ["thing4", 17]

My attempt:

resultDict = primaryDict.Keys.Intersect(secondaryDict.Keys).ToDictionary(t => t.Key, t.Value);

This obviously does not work because the primaryDict.Keys.Intersect is returning a list of keys... how would I reestablish a new dictionary, or pair down the primary dictionary? Any help would be appreciated.

Racon answered 21/5, 2012 at 12:18 Comment(0)
J
31

You could do in this way:

resultDict =  primaryDict.Keys.Intersect(secondaryDict.Keys)
                              .ToDictionary(t => t, t => primaryDict[t]);

or, alternatively:

resultDict =  primaryDict.Where(x => secondaryDict.ContainsKey(x.Key))
                         .ToDictionary(x => x.Key, x => x.Value);

the latter maybe is slightly more efficient because avoids the creation of a throw-away collection (the one generated by the Intersect method) and does not require a second access-by-key to primaryDict.

EDIT (as per comment) :

resultDict =  
primaryDict.Where(x => secondaryDict.ContainsKey(x.Key))
           .ToDictionary(x => x.Key, x => x.Value + secondaryDict[x.Key]);
Jaco answered 21/5, 2012 at 12:24 Comment(10)
I think the last version is much better, as I don't think treating the dictionary as an IEnumerable will leverage the Dictionary, and will run in O(n) time.Guesthouse
That worked great for what I'm doing... I used the second solution and everything is working as expected. You rock Dave!Racon
As a follow up... is it possible to sum the values in this same expression?Racon
@StewartBasterash: The values in primaryDict with the ones in secondaryDict having the same keys?Jaco
Yes... I am capturing and evaluating data across different domains. The different dictionaries maintain the data for a given domain... The key indicates an element within that domain, and the value is how it was presented in that domain... I am attempting to do some additional calculation... I need to do statistical analysis on a given element (key), across multiple domains (dictionary), based on values for each key... I hope this makes sense?Racon
Got it... That makes sense... sorry for my ignorance... I am new to writing Lambda in .NET, but I'm really loving this stuff for the things that I do with data mining...Racon
@StewartBasterash: don't worry, LINQ and lambda expressions can be pretty difficult at the beginning ;)Jaco
how can i do this based on values.?? Intersection is working but i want to convert it to dictionary.. So .ToDictionary(t => t, t => primaryDict[t]); part gives errorCalcutta
@SRJ: if you're intersecting values you can't use primaryDict[value], but maybe I didn't get your problem... anyway I suggest you to open a new questionJaco
Is this faster than linear? How fast is this?Ophidian
P
4

You can still use primaryDict within your Linq statement since you are creating a new dictionary, which only gets assigned to your variable once it is created:

resultDict = primaryDict.Keys
                        .Intersect(secondaryDict.Keys)
                        .ToDictionary(t => t, primaryDict[t]);
Piaffe answered 21/5, 2012 at 12:23 Comment(0)
A
2

Untested:

resultDict = primaryDict.Keys.Intersect(secondaryDict.Keys).ToDictionary(t => t.Key, primaryDict[t.Key]);
Anton answered 21/5, 2012 at 12:23 Comment(0)
I
0

If you want to select out an object with the "value" of both dictionaries, because that what you probably want, the you can try something like this. Assuming that the keys for both dictionaries are the same i.e. that map each together, like a GUID between two systems

dictA.Keys.Intersect(dictB.Keys).Select(x => new MyMappingClass
{
    dictAValue= dictA[x], dictBValue= dictB[x]
})
Icehouse answered 26/6, 2020 at 22:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.