0

I have list of objects with three keys and I want to convert it to three levels of lookups (or dictionaries):

class MyClass
{
    public int Key1;
    public int Key2;
    public int Key3;
    public float Value;
}
...

IEnumerable<MyClass> table = new List<MyClass>()
{
    new MyClass(){Key1 = 11, Key2 = 21, Key3 = 31, Value = 1},
    new MyClass(){Key1 = 11, Key2 = 21, Key3 = 32, Value = 2},
    new MyClass(){Key1 = 11, Key2 = 22, Key3 = 31, Value = 3},
    new MyClass(){Key1 = 11, Key2 = 23, Key3 = 33, Value = 4},
    new MyClass(){Key1 = 12, Key2 = 21, Key3 = 32, Value = 5},
    new MyClass(){Key1 = 12, Key2 = 22, Key3 = 31, Value = 6}

};

I want the result to be of type:

ILookup<int, ILookup<int, Dictionary<int, float>>>

or

Dictionary<int, Dictionary<int, Dictionary<int, float>>>

I tried:

ILookup<int, MyClass> level1 = table.ToLookup(i => i.Key1, i => i);
ILookup<int, ILookup<int, MyClass>> level2 = level1.ToLookup(
    i => i.Key, i => i.ToLookup(j => j.Key2, j => j));
ILookup<int, ILookup<int, Dictionary<int, float>>> level3 = ?

, but I'm stucked in third level. It's probably a dupe, but what I'm looking for is probably buried under tons of questions about lists of objects with parent-child relation. [1] [2] [3] [4]

saastn
  • 5,717
  • 8
  • 47
  • 78
  • I believe that those key duplications are rejecting your ideas with lookups and dictionaries. What you are looking for is probably a weighted graph or just 2d array which will reflect the relations. If you would really want to build that structure you would need to create unique identifier in first key paramenter of this `Dictionary>>` structure – Pawel Nov 03 '20 at 23:04

2 Answers2

2

It's a bit of an eyeful and not readable at all but this will sort you out:

ILookup<int, ILookup<int, Dictionary<int, float>>> result = table
                .ToLookup(i => i.Key1)
                .ToLookup(i => i.Key, i => i.ToLookup(j => j.Key2)
                .ToLookup(x => x.Key, x => x.ToDictionary(y => y.Key3, y => y.Value)));
Peter Csala
  • 17,736
  • 16
  • 35
  • 75
JohanP
  • 5,252
  • 2
  • 24
  • 34
0

If you are certain that every combination of {Key1, Key2, Key3} is unique, you can create a Dictionary. A fetch value from the Dictionary will return one float.

If there might be duplicate combinations of {Key1, Key2, Key3}, then you need to create a LookupTable. A fetch returns the sequence of all original values that have this combination of keys.

For this you need the overload of Enumerable.ToLookup or the overload of Enumerable.ToDictionary with both a keySelector and an ElementSelector.

  • key: new {Key1, Key2, Key3}
  • element: Value

So:

IEnumerable<MyClass> table = ...
var lookupTable = table.ToLookup(

    // parameter keySelector: for every object of MyClass take the keys:
    myObject => new
    {
       Key1 = myObject.Key1,
       Key2 = myObject.Key2,
       Key3 = myObject.Key3,
    },

    // parameter elementSelector: for every object of MyClass take the Value
    myObject => myObject.Value);

ToDictionary is similar:

var dictionary = table.ToLookup(myObject => new
    {
       Key1 = myObject.Key1,
       Key2 = myObject.Key2,
       Key3 = myObject.Key3,
    },
    myObject => myObject.Value);

Usage:

var keyToLookup = new 
{
    Key1 = 7,
    Key2 = 14,
    Key3 = 42,
};

float lookedUpValue = dictionary[keyToLookup];
IEnumerable<lookedUpValues = lookupTable[keyToLookup];

Simple comme bonjour!

Harald Coppoolse
  • 28,834
  • 7
  • 67
  • 116