2016-12-07 5 views
2

Я читаю таблицу SQL из SQl SERVER, используя код C#.Словарь словарей в C#

Мои данные выглядит следующим образом:

ZOO Animal Mn Tu 
NDS  BAT  2 0 
GOR  BAT  3 1 
VTZ  BAT  1 2 
MAS  BAT  0 0 
CST  BAT  0 0 
NDS  CAT  4 0 
GOR  CAT  4 0 
VTZ  CAT  2 0 
MAS  CAT  7 0 
CST  CAT  1 0 
NDS  DOG  3 0 
GOR  DOG  2 0 
VTZ  DOG  1 0 
MAS  DOG  3 0 
CST  DOG  0 1 
NDS  EGG  7 0 
GOR  EGG  2 0 
VTZ  EGG  0 0 
MAS  EGG  0 0 
CST  EGG  4 0 

я написал SQL команду чтения, и он идет

sql = "SELECT * FROM table"; 

OleDbCommand cmd = new OleDbCommand(sql, conn); 
     cmd.CommandTimeout = 600; 
     using (OleDbDataReader reader = cmd.ExecuteReader()) 
     { 


      while (reader.Read()) 
      { 
       var location = reader.GetString(0).Trim(); 
       var animal= reader.GetString(1).Trim(); 
       var Monday= reader.GetValue(1).ToString().Trim(); 
       var Tuesday= reader.GetValue(3).ToString().Trim(); 

      } 
     } 

Я создал словарь следующим образом:

private Dictionary<string, Dictionary<string, Dictionary<string, string>>> zooDict; 
zooDict= new Dictionary<string, Dictionary<string, Dictionary<string, string>>>(); 

Я бы идеально хотели бы иметь такую ​​структуру:

{ 
NDS: 
    { 
    BAT: 
     {Mn: 2, 
     Tu: 2}, 
    CAT: 
     { 
     MN: 4, 
     Tu: 0 
     } 
    DOG: 
     { 
     MN: 3, 
     Tu: 0 
     } 

    EGG: 
     { 
     MN: 7, 
     Tu: 0 
     } 


    } 
    GOR: 
     . 
     . 
     . 
     . 
     . 

} 

Я надеюсь преобразовать этот словарь в json-файл, но я не могу добавить ключи и значения в пустой словарь. Я пришел из фона python, где я могу использовать defaultdict для создания словаря словарей без использования ключевых ошибок.

Любые советы по созданию словаря будут чрезвычайно оценены.


if (!ZooDict.ContainsKey(location)) 
{ 
    var catDict = new Dictionary<string, string>(); 
    catDict.Add("Mon", Monday); 
    catDict.Add("Tue", Tuesday); 
    var AnimalDict = new Dictionary<string, Dictionary<string, string>>(); 
    AnimalDict.Add(animal, catDict); 
    waitlistDict.Add(location, AnimalDict); 
} 
else 
{ 
    if (!waitlistDict[location].ContainsKey(animal)) 
    { 
     var catDict = new Dictionary<string, string>(); 
     catDict.Add("Mon", Monday); 
     catDict.Add("Tue", Tuesday); 
     var AnimalDict = new Dictionary<string, Dictionary<string, string>>(); 
     AnimalDict.Add(animal, catDict); 
     waitlistDict[location] = AnimalDict; 
    } 
    else 
    { 
     if (waitlistDict[location][animal].ContainsKey("Mon")) 
     { 
      waitlistDict[location][animal]["Mon"] = Monday; 
     } 
     else 
     { 
      waitlistDict[location][animal]["Mon"] = Monday; 
     } 
     if (waitlistDict[location][animal].ContainsKey("Tue")) 
     { 
      waitlistDict[location][animal]["Tue"] = Tuesday; 
     } 
     else 
     { 
      waitlistDict[location][animal]["Tue"] = Tuesday; 
     } 
    } 
} 
+2

Ваш подход является правильным. Но вам нужно создать самый внутренний экземпляр словаря. Используйте 'zooDict.Add (« ключ », новый словарь();' где 'key' ** ** bat ** и т. Д. –

+0

Мне не удалось добавить внутренние словари, но теперь я думаю, что у меня есть. – Morpheus

+0

Можете ли вы показать мне как вы добавляете внутренний словарь? Я могу помочь вам или исправить ваш подход к добавлению словаря. –

ответ

6

Вы можете заполнить словарь непосредственно в цикле

private Dictionary<string, Dictionary<string, Dictionary<string, string>>> zooDict = 
    new Dictionary<string, Dictionary<string, Dictionary<string, string>>>(); 

while (reader.Read()) 
{ 
     var location = reader.GetString(0).Trim(); 
     var animal= reader.GetString(1).Trim(); 
     var Monday= reader.GetValue(1).ToString().Trim(); 
     var Tuesday= reader.GetValue(3).ToString().Trim(); 

     if(!zooDict.ContainsKey(location)) 
      zooDict[location] = new Dictionary<string, Dictionary<string, string>>(); 

     zooDict[location][animal] = new Dictionary<string, string>() 
     { 
      { "MN", Monday }, 
      { "Tu", Tuesday } 
     }; 
} 

В качестве примечания, вы можете рассмотреть вопрос о создании классов для представления ваших объектов, добавьте их в словарь или список , и используйте Newtonsoft Json.net (http://www.newtonsoft.com/json), чтобы сериализовать их, а не использовать словари для всего. Например, вы можете создать класс:

public class Animal 
{ 
    public string Name { get; set; } 
    public int Monday { get; set; } 
    public int Tuesday { get; set; } 
} 

var zooDict = new Dictionary<string, List<Animal>>(); 

// then in your while loop you do this 
if(!zooDict.ContainsKey(location)) 
    zooDict[location] = new List<Animal>(); 
zooDict[location].Add(new Animal() { /* fill Monday and Tuesday properties */ }); 

Конечно, вы можете сделать еще один шаг вперед и создать класс со свойствами string Location и List<Animal> Animals и устранить словари в целом. Это зависит от вашего случая использования (ы) я думаю

+3

. Классы были бы намного проще. – TheGeekYouNeed

+0

@ TheGeekYouNeed Я не очень хорошо знаком с C#. Надеюсь, классы решат проблему. Мне спорадически приходится иметь дело с кодом, написанным другими. следовательно, путаница. – Morpheus

+0

Morpheus прав, классы устраняют разочарования здесь – TheQuestioner

5
public class DataLine 
{ 
    public string Zoo { get; set; } 
    public string Animal { get; set; } 
    public int Mn { get; set; } 
    public int Tu { get; set; } 
} 
public IEnumerable<DataLine> ReadAllLines() 
{ 
    ... 
    using (OleDbDataReader reader = cmd.ExecuteReader()) 
    { 
     while (reader.Read()) 
     { 
      yield return new DataLine() { Zoo = reader.GetString(0).Trim(), Animal = reader.GetString(1).Trim(), Mn = reader.GetInt32(2), Tu = reader.GetInt32(3) }; 
     } 
    } 
} 
var dictionary = ReadAllLines() 
    .GroupBy(line => line.Zoo) 
    .ToDictionary(zoo => zoo.Key, 
        zoo => zoo.ToDictionary(animal => animal.Animal, 
              animal => new { animal.Mn, animal.Tu })); 

var sb = new StringBuilder(); 

using (var sw = new System.IO.StringWriter(sb)) 
{ 
    new Newtonsoft.Json.JsonSerializer().Serialize(sw, dictionary); 
} 

Console.WriteLine(sb.ToString()); 
+0

Я предпочитаю этот ответ намного больше, чем мой, и я не думаю, что для сериализации потребуется какая-то обычная логика, upvote – KMoussa

Смежные вопросы