1

I'm using the answer from this link Linq join two dictionaries using a common key

to produce the result that I want. Unfortunately, I'm not sure how to convert the result back into a dictionary object, since the result is some type of System.Linq.Enumerable+WhereSelectEnumerableIterator and I'm not sure what to do with that.

Okay, specifics. Suppose I have the following:

[Flags]
enum People { Adam = 0x1, Barry = 0x2, Chris = 0x4, David = 0x8, 
            Eric = 0x10, Frank = 0x20, George = 0x40, Harold = 0x80 };

Dictionary<string, People> EUInterest = new Dictionary<string, People>() { 
    { "athletes", People.Adam | People.Barry }, 
    { "artists", People.Frank | People.Harold } };

Dictionary<string, People> USInterest = new Dictionary<string, People>() { 
    { "athletes", People.Chris | People.Harold }, 
    { "artists", People.Eric } };

var result = from interest in EUInterest.Keys
             where USInterest.ContainsKey(interest)
             let v1 = EUInterest[interest]
             let v2 = USInterest[interest]
             select new Dictionary<string, People>() { {interest, v1 | v2 } };

When I look at result in the debugger, I see the "Results View" has almost what I want it to have. It looks like it creates two dictionaries with a single Key. Which, now that I look closely at the query, that's exactly what it does.

Here is what I want the result to be:

Dictionary<string, People> result =  new Dictionary<string, People>() { 
    { "athletes", People.Adam | People.Barry | People.Chris | People.Harold }, 
    { "artists", People.Frank | People.Harold | People.Eric } };

Even if I'm able to get the var result how I want it from the select query, I'm not sure how to access that data, because it won't be a Dictionary object. (I can easily use the wonderful merge extension that Andrew Orsich provided here: Merging dictionaries in C#)

Community
  • 1
  • 1
Machtyn
  • 2,982
  • 6
  • 38
  • 64

2 Answers2

1

Do you want something like this after your result?

        var finalDic = new Dictionary<string, People>();

        foreach (var dic in result) {
            foreach (var key in dic.Keys) {
                People people;
                if (finalDic.TryGetValue(key, out people)) {
                    finalDic[key] = people | dic[key];  
                }
                else {
                    finalDic[key] = dic[key];
                }                   
            }
        }

//Output

athletes: Adam, Barry, Chris, Harold

artists: Eric, Frank, Harold

But you can simple take you first dictionary as a initial object and use the second to do something similar as i dit above:

        var EUxUSInterest = new Dictionary<string, People>(EUInterest);

        foreach (var element in USInterest) {
            People people;
            if (EUxUSInterest.TryGetValue(element.Key, out people)) {
                EUxUSInterest[element.Key] = people | element.Value;    
            }
            else {
                EUxUSInterest[element.Key] = element.Value;
            }   
        }

//Output is the same

athletes: Adam, Barry, Chris, Harold

artists: Eric, Frank, Harold

George
  • 777
  • 7
  • 17
  • Yes, I suppose I'm trying to make it more difficult than it needs to be. My only question is would this iteration be costly based on how many false iterations it creates. – Machtyn Jul 24 '15 at 18:07
  • Yes, I am making it more difficult than it needs to be since my solution below essentially throws in a middle set of steps to do exactly what your solution does in the first place. – Machtyn Jul 24 '15 at 18:16
  • i see, i just got you final object but i believe you can improve by doing something similar before your original result query, see the update – George Jul 24 '15 at 18:21
0

Well, this may not be the most efficient way to do it (I'll look into the HashSet idea). The answer on my question about the query is that I should use it in the foreach loop raw. I was trying to use the query by accessing some property.

This answer uses the MergeLeft Dictionary extension mentioned in the question above.

[Flags]
enum People
{
    None = 0x0, Adam = 0x1, Barry = 0x2, Chris = 0x4, David = 0x8, 
    Eric = 0x10, Frank = 0x20, George = 0x40, Harold = 0x80, Ian = 0x100, 
    Joe = 0x200, Larry = 0x400, Mark = 0x800, Nathan = 0x1000, Oscar = 0x2000, 
    Paul = 0x4000, Roger = 0x8000, Sam = 0x10000, Tom = 0x20000, 
    Victor = 0x40000, Walter = 0x80000,Yogi = 0x100000, Zane = 0x200000
};

Dictionary<string, People> EUInterest = new Dictionary<string, People>() { 
{ "athletes", People.Adam | People.Barry }, 
{ "artists", People.Frank | People.Harold } };
Dictionary<string, People> USInterest = new Dictionary<string, People>() { 
{ "athletes", People.Chris | People.Harold }, 
{ "artists", People.Eric } };

var query = from interest in EUInterest.Keys
                where USInterest.ContainsKey(interest)
                let v1 = EUInterest[interest]
                let v2 = USInterest[interest]
                select new Dictionary<string, People>() { {interest, v1 | v2 } };

Dictionary<string, People> temp = new Dictionary<string, People>();
foreach (var a in query)
{
    temp = temp.MergeLeft(a);
}

foreach (People option in Enum.GetValues(typeof(People)))
{
    if (temp["athletes"].HasFlag(option))
        Console.WriteLine("{0} IS AN ATHLETE.", option);
    // else Console.WriteLine("{0} is not an athlete.", option);
}
Machtyn
  • 2,982
  • 6
  • 38
  • 64