Creating a dictionary from another dictionary

From a tab limited text file like this, first row: names of columns, rest of the rows the values for eahc column,...

Col1    Col2    Col3    Col4    Col5    Col6    Col7    Col8....
Val1    Val2    Val3    Val4    Val5    Val6    Val7    Val8...
abc1    abc2    abc3    abc4    abc5    abc6    abc7    abc8...
.....
......
......

I have made a Dictionary<combinedKey, List<MyRows> myList> where combinedKey is values for Col1+Col2+Col3 so I have made a key based on those, and then if there are more rows in the file with the same combinedKey I am making a list of them, so that's why it is a dictionary. And it serves the purpose of the thing I am doing so far based on requirements. I am not gonna hcange that! That's what I need for that part of the problem. :)

Now in some other part of the program I need another combinedKey, this time: Col1+Col2+Col3+Col4+Col5 Is there a way I can utilize my previously parsed and populted dictionary above?

Upvotes: 1

Views: 336

Answers (1)

Matthew Haugen
Matthew Haugen

Reputation: 13286

Interesting question. Unfortunately there isn't really a great way to do this, at least that I know of. No matter what you're going to have to touch each record multiple times, so you might as well just use LINQ for both groups and have them independent. This will, at least, be more readable.

I'll just pretend your data is tab-delimited. Given that, you can do something like this.

var rows = File.ReadAllLines(filePath).Select(c => 
                                              {
                                                  string[] args = c.Split(\t);

                                                  return new
                                                  {
                                                      Col1 = args[0],
                                                      Col2 = args[1],
                                                      Col3 = args[2],
                                                      Col4 = args[3],
                                                      Col5 = args[4],
                                                      Col6 = args[5],
                                                      Col7 = args[6],
                                                      Col8 = args[7]
                                                  };
                                              }).ToArray(); // I wouldn't use ToArray here if you were only looking for one grouping, since that would be less efficient on memory and CPU usage

var groupedByThree = rows.GroupBy(c => c.Col1 + c.Col2 + c.Col3);

var groupedByFive = rows.GroupBy(c => c.Col1 + c.Col2 + c.Col3 + c.Col4 + c.Col5);

I know this is more than you were asking about, since I included some parsing logic which is almost definitely not applicable to your particular situation. But that's how I'd do it. Build a flat list first, then group each set independently.

I mean, of course, you could always do something similar to this and use the parsing and grouping you've already got, but it wouldn't be more performant in the complexity sense, and I think it's less readable.

var dict = new Dictionary<combinedKey, List<MyRows>>(); // your data here

var dimensioned = dict.ToDictionary(c => c.Key, c => c.Value.ToDictionary(x => x.Col4 + x.Col5));

As you can read, this creates a dictionary of dictionaries that looks something like this:

{
    col1col2col3
    {
        col4col5
        {
            individual records
        }
    }
}

You can flatten that out as you please. Although if you can, I'd leave it hierarchical like that. You can use this like this:

foreach(var record in dict[col1col2col3][col4col5])
{
    // handle
}

Or you could even reverse to get the original dictionary:

dict[col1col2col3].SelectMany(c => c.Value);

In fact, I'd be tempted to parse the original dictionary into something like this right from the start, then you're only storing it once in memory. But again I would just parse it all using LINQ.

Upvotes: 1

Related Questions