Reputation: 6015
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]
Upvotes: 0
Views: 1677
Reputation: 30464
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.
new {Key1, Key2, Key3}
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!
Upvotes: 0
Reputation: 5472
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)));
Upvotes: 2