0

I'm trying to build this datastructure with a nested dictionary:

["A",["A",123]],
["B",["B",123]],
["C",["C",123]],

And then loop over the data structure and print out the values.

The first problem is, that all the nested dictionaries are the same {"C",123}. I think it's because it is the same object, but I don't know how to overcome that. Can I dynamically create new objects in the loop ?

The other problem i face is in the loop where I try to print out the Values. The compiler says that it can't convert Dictionary to Dictionary.

using System;
using System.Collections.Generic;

namespace ConsoleApp1
{
    class Program
    {
        public static void Main()
        {
            List<string> liste = new() { "A", "B", "C" };
 
            Dictionary<string, Dictionary<string, int>> DictOfDicts = new();
            Dictionary<string, int> DictOfData = new();

            foreach (string i in liste)
            {
                DictOfData.Clear();
                DictOfData.Add(i, 123);
                DictOfDicts.Add(i, DictOfData);
            }
            foreach (Dictionary<string, int> i in DictOfDicts)
            {
                Console.WriteLine("Some result");
            }
        }
    }
}
Rodrigo Rodrigues
  • 7,545
  • 1
  • 24
  • 36
Kresten
  • 810
  • 13
  • 36
  • Variable names should begin in lowercase, so they don't get confused with class names, which start in uppercase. – Progman Jun 06 '21 at 09:55
  • Does this answer your question? [Why does my ArrayList contain N copies of the last item added to the list?](https://stackoverflow.com/questions/19843506/why-does-my-arraylist-contain-n-copies-of-the-last-item-added-to-the-list) – Progman Jun 06 '21 at 09:56
  • `foreach (Dictionary i in DictOfDicts.Values)` – bolkay Jun 06 '21 at 09:56
  • 1
    Just move your `Dictionary DictOfData = new();` to inside the `foreach` loop. – Rodrigo Rodrigues Jun 06 '21 at 10:28
  • 1
    I think this other question may solve the first part of the quesiton, but I'm skilled in java, so I'm not sure. – Kresten Jun 06 '21 at 10:31
  • BTW, you just need this: `liste.ToDictionary(x => x, x => new[] { x, "123" })` – Rodrigo Rodrigues Jun 06 '21 at 10:37
  • 1
    @RodrigoRodrigues - No, the OP needs `liste.ToDictionary(x => x, x => new Dictionary() { { x, 123 } })`. – Enigmativity Jun 06 '21 at 11:00
  • @Kresten - You have 3 good answers and one bad one - and you've accepted the bad one. It does not solve your problem. It's effectively the same. Please reconsider your choice. – Enigmativity Jun 06 '21 at 22:28

4 Answers4

2

You declared DictOfData outside of the foreach loop. Then, all the operations inside the loop are done on the same object. So, you are clearing and filling the same dictionary object over and over again, on each loop iteration.

Just move you declaration of DictOfData to inside the loop, and you'll be good to go.


Bonus:

The whole operation you displayed in the questions can be done with just this:

liste.ToDictionary(x => x, x => new Dictionary<string, int>() { { x, 123 } })
Rodrigo Rodrigues
  • 7,545
  • 1
  • 24
  • 36
  • 2
    Actually, you got that wrong. What the OP needs is `liste.ToDictionary(x => x, x => new Dictionary() { { x, 123 } })`. Your code doesn't compile. – Enigmativity Jun 06 '21 at 11:00
1
var liste = new List<string>() { "A", "B", "C" };
var DictOfDicts = new Dictionary<string, Dictionary<string, int>>();

foreach (var i in liste)
{
  // Create here a new DictOfData to add it to DicOfCicts.
  var DictOfData = new Dictionary<string, int>();
  DictOfData.Add(i, 123);
  DictOfDicts.Add(i, DictOfData);
}

The structure of DicOfDicts is,

["A",["A",123]],
["B",["B",123]],
["C",["C",123]],
Themelis
  • 4,048
  • 2
  • 21
  • 45
  • 1
    Why do I need KeyValuePair in the foreach loop, when DictOfDicts already consists of KeyValuePairs? Why do I need to construct internalDict? Would my entry not already be a keyvalue pair? – Kresten Jun 06 '21 at 10:27
  • I was just being explicit here. Even if you just have a `foreach (var item in DictOfDicts)` the item is also of type `KeyPair`. That's what dictionaries are made of, key-value pairs. – Themelis Jun 06 '21 at 10:40
  • Seriously? You reuse the same instance of the dictionary and you selectively pick the one key to make the output match the OP's requirement. This is just smoke and mirrors. – Enigmativity Jun 06 '21 at 10:55
  • If you write out the full content of the nested dictionary, with your code, you get this: `[A,[A,123],[B,123],[C,123]] [B,[A,123],[B,123],[C,123]] [C,[A,123],[B,123],[C,123]]`. – Enigmativity Jun 06 '21 at 10:57
  • Can't blame someone when he's right @Enigmativity – Themelis Jun 06 '21 at 13:27
0

I've used a slightly older C# language specification for the answer, and made the type declarations more clear for you to understand.

List<string> list = new List<string>() { "A", "B", "C" };

Dictionary<string, Dictionary<string, int>> parent = new Dictionary<string, Dictionary<string, int>>();


foreach (string i in list)
{
    Dictionary<string, int> child = new Dictionary<string, int>();
    child.Add(i, 123);
    parent.Add(i, child);
}
foreach (KeyValuePair<string, Dictionary<string, int>> parentPair in parent)
{
    Dictionary<string, int> childDictionary = parentPair.Value;
    foreach (var childPair in childDictionary)
    {
        Console.WriteLine(childPair.Value);
    }
}
0

It's a very easy exercise to fix your code. Simply replace the DictOfData.Clear(); with the declaration of DictOfData itself. In other words, move the line Dictionary<string, int> DictOfData = new(); into the loop. That way you have a fresh instance of the nested dictionary rather than reusing the old one.

Try this code:

List<string> liste = new() { "A", "B", "C" };

Dictionary<string, Dictionary<string, int>> DictOfDicts = new();

foreach (string i in liste)
{
    Dictionary<string, int> DictOfData = new();
    DictOfData.Add(i, 123);
    DictOfDicts.Add(i, DictOfData);
}
foreach (KeyValuePair<string, Dictionary<string, int>> i in DictOfDicts)
{
    Console.WriteLine($"[{i.Key},{String.Join(",", i.Value.Select(x => $"[{x.Key},{x.Value}]"))}]");
}
Enigmativity
  • 113,464
  • 11
  • 89
  • 172