0

I am attempting to build and populate a data structure consisting of multiple, but variable count, nested dictionaries in C#. I am currently using a recursive function to do so.

The data stored in the structure is the contents of a PrintQueue's Location field parsed according to a naming convention. In this case, the convention is:

Campus-Building-Floor-Room-Subroom

The basic data structure would therefore be

(Dict)[Campus, (Dict)[Building, (Dict)[Floor, (Dict)[Room, (Dict)[Subroom, (List)[PrintQueue]]]]]]

Unfortunately I can't assume every campus will have the same naming convention, and getting each campus to switch is not feasible. Hence the need to make this dynamic.

Building the data structure initially works fine but populating it with data is proving an issue for me.

Everything works as intended for the initial drill down, but I'm struggling to wrap my head around how the function actually works so that I can add entries to the dictionaries when a key already exists.

My code right now is:

    private void popData()
    {
        var poppedData = new SortedDictionary<string, object>();

        var keyListList = new List<List<string>>()
        {
            new () {"UCSC","123","1","102","N/A"},
            new () {"UCSC","456","2","210","N/A"},
            new () {"UCSC","789","3","302","1"}
        };

        foreach (var list in keyListList)
        {
            var queue = "test";
            var queueList = new List<string>();
            poppedData = createDataDictionary(list, queue, queueList, poppedData);
        }
    }

    private dynamic createDataDictionary(List<string> keyList, string queue, List<string> queueList, SortedDictionary<string, object> tempData)
    {
        string temp = keyList.ElementAt(0).ToUpper();

        if (tempData.ContainsKey(temp))
        {
            keyList.RemoveAt(0);
            return createDataDictionary(keyList, queue, queueList, (SortedDictionary<string, object>)tempData[temp]);
        }
        else if (keyList.Count() > 1)
        {
            keyList.RemoveAt(0);
            tempData.Add(temp, createDataDictionary(keyList, queue, queueList, tempData));
            return tempData;
        }
        else if (keyList.Count() == 1)
        {
            queueList.Add(queue);
            return new SortedDictionary<string, List<string>>() { { temp, queueList } };
        }
        else
        {
            keyList.RemoveAt(0);
            return new SortedDictionary<string, object> { { temp, createDataDictionary(keyList, queue, queueList, tempData) } };
        }
    }

As I said, it does not currently work, and this version is actually worse than the one that functioned more or less correctly, but I lost that version for reasons.

I have tried many, many versions of this function but I am not good at visualizing recursion so most of it has just been banging my head against the wall with occasional incremental improvements.

My question is this: How do I adapt this recursive function to allow it to add relevant dictionaries at levels in the structure that have existing keys?

13
  • Might you please edit your question and share a minimal reproducible example as suggested in How to Ask? As it is your code does not compile because PrintQueue is undefined, see dotnetfiddle.net/p0IKuW. So please share a minimal version of this type (or remove it if you don't need it) and also share some inputs and outputs that are working incorrectly. My demo fiddle here serializes the returned dictionary to JSON, maybe you could share your required output as JSON? Commented Aug 4 at 17:19
  • Apart of the previous comments, why do you do test tempData.ContainsKey(temp) == false which is mandatory true because being in the else branch of if (tempData.ContainsKey(temp)) ? Commented Aug 4 at 17:23
  • 1
    It seems like your proposed structure is unnecessarily complex. If the objects (Campus, Building, Floor, Room, and Subroom) all have IDs then just make a separate Dictionary for each one (no nesting and no recursion) and use LINQ to query and join the results you need. Commented Aug 4 at 18:01
  • Please re-read your question and see if you can edit it to include an minimal reproducible example - which requires clear input and desired output along with code. Currently question reads like "here is code that does not work, I don't know what needs to be done, help me"... Commented Aug 4 at 18:12
  • @dbc PrintQueue is part of the System.Printing libary, which is part of the WPF framework. I've included the 'using' statement. Also, I am using dynamic because the bottom dictionary has a Value of type List<PrintQueue>, and the compiler didn't like that when I had it set as a SortedDictionary<string, object>. Commented Aug 4 at 18:19

1 Answer 1

1

Figured it out. Had to restructure the whole thing, turn it into a void function, but ultimately it works, so I'm happy.

Here's the function:

    private void popData()
    {
        var poppedData = new SortedDictionary<string, object>();

        var keyListList = new List<List<string>>()
        {
            new () {"UCSC","123","1","102","N/A"},
            new () {"UCSC","456","2","210","N/A"},
            new () {"UCSC","789","3","302","1"}
        };

        foreach (var list in keyListList)
        {
            var queue = "test";
            var queueList = new List<string>();
            poppedData = createDataDictionary(list, queue, queueList, poppedData);
        }
    }

    private void createDataDictionary(List<string> keyList, string queue, List<string> queueList, SortedDictionary<string, object> tempData)
    {
        string temp = keyList.ElementAt(0).ToUpper();
        keyList.RemoveAt(0);

        if (tempData.ContainsKey(temp) == false && keyList.Count() > 0)
        {
            if (queueList.Contains(queue) == false)
                queueList.Add(queue);

            var tempDict = new SortedDictionary<string, object>();
            createDataDictionary(keyList, queue, queueList, tempDict);
            tempData.Add(temp, tempDict);
        }
        else if (keyList.Count() == 0)
        {
            if (tempData.ContainsKey(temp) == false)
            {
                if (queueList.Contains(queue) == false)
                    queueList.Add(queue);

                tempData.Add(temp, queueList);
            }
            else
            {
                var tempList = (List<string>)tempData[temp];
                tempList.Add(queue);
            }
        }
        else
        {
            createDataDictionary(keyList, queue, queueList, (SortedDictionary<string, object>)tempData[temp]);
        }
    }
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.