Criar dictionary (do dictionary) usando o agrupamento no Linq

Eu sei que eu poderia fazer isso com loops (na verdade, eu estou atualmente, mas estou tentando aprender / melhorar minhas habilidades no Linq e também espero que ele forneça uma solução mais eficiente. Então, aqui está o meu cenário:

Digamos que eu tenha as 3 listas seguintes (estou apenas inventando um exemplo semelhante, então perdoe a estupidez):

Dim lstTeachers as New List(of string) Dim lstStudentsSex as New List(of string) Dim lstStudentName as New List(of string) 

E eles são, por exemplo, da seguinte maneira:

 lstTeachers: lstStudentsSex: lstStudentName: Teacher 1 Male Whatever Name 1 Teacher 2 Female Whatever Name 2 Teacher 1 Female Whatever Name 3 Teacher 1 Female Whatever Name 4 Teacher 2 Male Whatever Name 5 Teacher 3 Male Whatever Name 6 Teacher 3 Female Whatever Name 7 Teacher 1 Male Whatever Name 8 Teacher 1 Female Whatever Name 9 Teacher 2 Male Whatever Name 10 

Onde cada input em cada lista corresponde às outras inputs com o mesmo índice – Basicamente como uma tabela de dados, apenas armazenada em listas separadas.

Agora, suponha que eu queira criar a seguinte estrutura com os seguintes valores:

 Dim dictTeacherSexName as New Dictionary(Of String, Dictionary(Of String, List(of String))) Dict1_Key: Dict1_Value / Dict2_Key: Dict2_Value: Teacher 1 Male Whatever Name 1 Whatever Name 8 Female Whatever Name 3 Whatever Name 4 Whatever Name 9 Teacher 2 ... 

… Espero que isso explique o que estou procurando realizar.

Agora, novamente, eu sei que esta pode ser uma idéia estúpida, mas também estou perguntando porque eu quero melhorar minhas habilidades com o Linq – especialmente Group By e várias seleções que ainda me pegam, então, por favor, ajude.

Muito obrigado!

As três listas tornam as coisas um pouco difíceis, mas não impossíveis. Você primeiro compactou as listas como sugerido por @ fsimonazzi ou baseou sua consulta nos índices da lista em vez das inputs da lista. O resultado poderia ser assim:

(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>> 

Não é ótimo que você tenha listas separadas com informações discretas, em vez de uma única lista com instâncias do aluno. Se você quiser usar o group by here, provavelmente precisará compactar as collections primeiro em um único enumerável com triplets e começar a usar as operações de consulta naquele enumerável.

Isso é mais ou menos a solução do Spender, mas isso funciona.

Em 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))); 

Eu só C #, não VB. Desculpas antecipadamente.

Vamos começar fazendo uma lista única de objects anônimos com propriedades teacher , sex , name :

 var singleList = lstTeachers .Zip(lstStudentsSex, (teacher, sex) => new {teacher, sex}) .Zip(lstStudentName, (x,name) => new {x.teacher, x.sex, name}) 

Agora podemos transformar isso em um Dicionário de dictionarys:

 singleList .GroupBy(x => x.teacher) .ToDictionary( g => g.Key, g => g.ToDictionary(x => x.sex, x => x.name)) 

Veja @ nawfal’s para uma versão corrigida do meu código.