2

How Can I Add additional Dictionary Object below

var topLevel1 = resultRows.GroupBy(g => g["CustomerAccountType"])
.ToDictionary(g => g.Key, g => g.ToList());

I want to add this within the LINQ line

  new Dictionary<string, object> { {"children", someDictionaryAgain}}

I want to append additional dictionary object after the .ToDictionary()

something like

var topLevel1 = resultRows.GroupBy(g => g["CustomerAccountType"])
.ToDictionary(g => g.Key, g => g.ToList()).Add(new Dictionary<string, object> {     {"somekey", "somevalueorobject"}}

Here is the expected output I wanted.

var toplevel = Dictionary <stirng, object> {
  {"Actual1", 0},
  {"Actual2", 0}
 }

After .ToDictionary() --> What code is best to use to achieve

    var toplevel = Dictionary <stirng, object> {
      {"Actual1", 0},
     {"Actual2", 0},
     {"AddedDynamically",0}
 }
agentpx
  • 1,051
  • 1
  • 8
  • 24

5 Answers5

3

ToDictionary outputs a Dictionary, so you can easily save the result into a variable and add to it. To ensure you're getting a string and object dictionary, though, you'll need to explicitly reference the types.

var topLevel1 = resultRows
    .GroupBy(g => g["CustomerAccountType"])
    .ToDictionary(
        g => g.Key,                                // This is fine since it returns a string
        g => { return g.ToList() as object; });    // Explicitlyreturn this as an object
topLevel1.Add("somekey", "somevalueorobject");

To expand nested collections, use SelectMany instead of Select

var topLevel1 = resultRows
    .GroupBy(g => g["CustomerAccountType"])
    .SelectMany(g => g.Select(v => new { Key = g.Key, Value = v })) // This creates an anonymous type for use further into the query
    .ToDictionary(
        g => g.Key,
        g => g.Value);
David
  • 10,458
  • 1
  • 28
  • 40
  • Looks close, but can we do that in one line? i need lambda because the additional "somekey" will be children of the first dictionary. – agentpx Dec 22 '14 at 18:28
  • The doing of this in one line for children of each dictionary? `.SelectMany` - I'll update my answer accordingly – David Dec 22 '14 at 20:22
  • Nope I will take care of the children object "somevalueObject" I just need to make your sample one LINQ syntax one liner. Not after the fact of creating topLevel1. I'll wait for your update. Thanks. – agentpx Dec 22 '14 at 20:27
2

You can't do this, for multiple reasons.

Primarily, because ToDictionary returns a new dictionary object (which you then assign). Calling Add on this returns void, so you can't do the assignment.

Basically, you have to leave your first line alone. To do the merge, you need to do a foreach. This part of the question has been discussed before at: Merging dictionaries in C#

Basically you end up with a loop:

foreach (KeyValuePair<string, object> kvp in secondDictionary)
    topLevel1.Add(kvp.Key, kvp.Value);

Note that the code above will break on a duplicate key.

Community
  • 1
  • 1
BradleyDotNET
  • 60,462
  • 10
  • 96
  • 117
1

you can try something like this:

var topLevel1 = resultRows
.GroupBy(g => g["CustomerAccountType"])
.ToDictionary(
    g => g.Key,                                
    g => { return g.ToList() as object; }).Union(new Dictionary<string, object> {     {"somekey", "somevalueorobject"}).ToDictionary(x=>x.Key,x=>x.Value);
niceman
  • 2,653
  • 29
  • 57
  • this will not add duplicate entries since union means all shared and non-shared elements just once. – niceman Dec 22 '14 at 18:45
0

If you use something like:

Dictionary<string,Dictionary<string,object>>

then you have the dictionary you are looking for ...

Anders H
  • 391
  • 4
  • 11
0
public class Test
{
    public static void test()
    {
        Dictionary<string, int> d1 = new Dictionary<string, int>();
        Dictionary<string, int> d2 = new Dictionary<string, int>();

        d1.AddRange(d2);
    }
}

public static class Extensions
{
    public static Dictionary<K, V> AddRange<K, V>(this Dictionary<K, V> d1, Dictionary<K, V> d2)
    {
        foreach (var kv in d2)
        {
            d1[kv.Key] = kv.Value;
        }
        return d1;
    }
}

Using this extension function will:

  • not fail upon duplicate key
  • return the starting dictionary so you have a fluent interface
John
  • 3,627
  • 1
  • 12
  • 13