I know I could do this with loops (as a matter of fact, I currently am, but I am trying to learn / imporve my Linq skills and i also hope it will provide a more efficent sol
It's not great that you have separate lists with the discrete pieces of information instead of a single list with Student instances. If you want to use group by here you'll probably need to zip the collections together first into a single enumerable with triplets and start using the query operations on that enumerable.
This more or less Spender's solution, but this works.
In C#
var dict = lstTeachers.Zip(lstStudentsSex, (teacher, sex) => new { teacher, sex })
.Zip(lstStudentName, (x, student) => new { x.teacher, x.sex, student })
.GroupBy(x => x.teacher)
.ToDictionary(g => g.Key, g => g.GroupBy(x => x.sex)
.ToDictionary(p => p.Key, p => p.Select(x => x.student)));
The three lists make things a bit difficult, but not impossible. Either you first zip the lists together as suggested by @fsimonazzi, or you base your query on the list indices rather than the list entries themselves. The result could look like this:
(C#)
var result = Enumerable
.Range(0, lstTeachers.Count)
.GroupBy(i => lstTeachers[i])
.ToDictionary(g => g.Key, g => g
.GroupBy(i => lstStudentsSex[i])
.ToDictionary(h => h.Key, h => h
.Select(i => lstStudentName[i])
.ToList()));
// result is Dictionary<string, Dictionary<string, List<string>>>
I only C#, not VB. Apologies in advance.
Let's start by making a single list of anonymous objects with properties teacher
, sex
, name
:
var singleList = lstTeachers
.Zip(lstStudentsSex, (teacher, sex) => new {teacher, sex})
.Zip(lstStudentName, (x,name) => new {x.teacher, x.sex, name})
Now we can turn this into a Dictionary of Dictionaries:
singleList
.GroupBy(x => x.teacher)
.ToDictionary(
g => g.Key,
g => g.ToDictionary(x => x.sex, x => x.name))
See @nawfal's for a corrected version of my code.