2013-01-21 200 views
0

我有一個像下面這樣類型的字典對象。使用C#對嵌套字典排序

Dictionary<string, Dictionary<Roles, Dictionary<Period, List<Product>>>> 

的角色(是一個枚舉),有「編制者」 &「審批人」作爲自己的物品。同樣,Period是另一個具有「前」&「過去」項目的枚舉。

列表中包含各種產品的列表。

我在字典中有以下層次結構中的項目。

"Sachin" --> Roles.Preparer --> Period.Past --> Products 
"Sachin" --> Roles.Approver --> Period.Ahead --> Products 
"Sachin" --> Roles.Approver --> Period.Ahead --> Products 
"Sachin" --> Roles.Approver --> Period.Past --> Products 

我將不得不按以下順序對字典進行排序。

"Sachin" --> Roles.Preparer --> Period.Ahead --> Products 
"Sachin" --> Roles.Approver --> Period.Ahead --> Products 
"Sachin" --> Roles.Preparer --> Period.Past --> Products 
"Sachin" --> Roles.Approver --> Period.Past --> Products 

此結構是必需的,因爲我將不得不迭代通過每個項目,並應添加爲郵件的一部分。

實際的代碼是這樣的。

`using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace Basics 
{ 
    class Product 
    { 
     public string Name { get; set; } 
     public int Days { get; set; } 

    } 

    enum Period 
    { 
     Ahead, 
     Past 
    } 

    enum Roles 
    { 
     Preparer, 
     Approver 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      DictionaryProcessing(new string[] { "[email protected]", "[email protected]" }); 
     } 

     private static void DictionaryProcessing(string[] emailIDs) 
     { 
      List<Product> products = new List<Product>(); 

      Product product1 = new Product() { Name = "Pencil", Days = 14 }; 
      Product product2 = new Product() { Name = "Eraser", Days = 2 }; 
      Product product3 = new Product() { Name = "Geometry Box", Days = 31 }; 

      products.Add(product1); 
      products.Add(product2); 
      products.Add(product3); 

      Dictionary<string, Dictionary<Roles, Dictionary<Period, List<Product>>>> dict = new Dictionary<string, Dictionary<Roles, Dictionary<Period, List<Product>>>>(); 

      /// 

      foreach (string emailID in emailIDs) 
      { 

       if (!dict.ContainsKey(emailID)) 
        dict.Add(emailID, new Dictionary<Roles, Dictionary<Period, List<Product>>>()); 

       if (!dict[emailID].ContainsKey(Roles.Preparer)) 
        dict[emailID].Add(Roles.Preparer, new Dictionary<Period, List<Product>>()); 

       if (!dict[emailID][Roles.Preparer].ContainsKey(Period.Ahead)) 
        dict[emailID][Roles.Preparer].Add(Period.Ahead, new List<Product>()); 

       if (!dict[emailID][Roles.Preparer].ContainsKey(Period.Past)) 
        dict[emailID][Roles.Preparer].Add(Period.Past, new List<Product>()); 

       /// 

       if (!dict[emailID].ContainsKey(Roles.Approver)) 
        dict[emailID].Add(Roles.Approver, new Dictionary<Period, List<Product>>()); 

       if (!dict[emailID][Roles.Approver].ContainsKey(Period.Ahead)) 
        dict[emailID][Roles.Approver].Add(Period.Ahead, new List<Product>()); 

       if (!dict[emailID][Roles.Approver].ContainsKey(Period.Past)) 
        dict[emailID][Roles.Approver].Add(Period.Past, new List<Product>()); 

       for (int i = 0; i < products.Count; i++) 
       { 
        dict[emailID][Roles.Preparer][Period.Ahead].Add(products[i]); 
        dict[emailID][Roles.Preparer][Period.Past].Add(products[i]); 
        dict[emailID][Roles.Approver][Period.Past].Add(products[i]); 
        dict[emailID][Roles.Approver][Period.Ahead].Add(products[i]); 
       } 


      } 
     } 
    } 
} 
` 

如何按此順序對其進行排序? 我僅限於使用.NET 2.0框架。

+0

我堅信這將是更容易維護,如果您使用的是標準的DataTable代替嵌套字典的讀取。 –

回答

1

字典無法排序。他們不是名單。另外:

你的結構是壞的 - 一個Dictionary不能包含相同的鍵不止一次,所以您提供的樣本,甚至沒有可能創造:

"Sachin" --> Roles.Preparer --> Period.Past --> Products 
"Sachin" --> Roles.Approver --> Period.Ahead --> Products 
"Sachin" --> Roles.Approver --> Period.Ahead --> Products 
"Sachin" --> Roles.Approver --> Period.Past --> Products 

「外」字典不能包含關鍵「薩欽」不止一次。 「內部字典」不能包含角色Approver不止一次,也是最後一級,Period.Past/Ahead不能超過一次。

改爲將結構改爲List<T>,其中T是一個合適的數據結構,或者像其他人已經注意到的那樣,改爲鍵入數據集,以便像處理表一樣處理結構。

編輯
我編輯我的答案,現在,只是爲了確保大家都明白是什麼大家都在談論。

我在說,字典不可能有兩次相同的密鑰。因此,根據這一規則,你的情況下,必須降低到以下幾點:

"Sachin" --> Roles.Preparer --> Period.Past --> Products 
"Sachin" --> Roles.Approver --> Period.Ahead --> Products 
"Sachin" --> Roles.Approver --> Period.Past --> Products 

現在,我們正在談論的事情適用於規則,我們可以問:「如何排序?」。答案是:你不能。字典根據定義是無序的結構。但是,您可以確保按特定順序檢索值。如果您想對產品進行「分類」,以便Past產品始終位於Ahead產品之前,請確保首先使用相應的密鑰。

EDIT 2

剛剛意識到這是基於複製/粘貼錯誤。你談論這些數據應閱讀:

"Sachin" --> Roles.Preparer --> Period.Ahead --> Products 
"Sachin" --> Roles.Preparer --> Period.Past --> Products 
"Sachin" --> Roles.Approver --> Period.Past --> Products 
"Sachin" --> Roles.Approver --> Period.Ahead --> Products 

你說你正在使用此代碼添加項目:

for (int i = 0; i < products.Count; i++) 
{ 
    dict[emailID][Roles.Preparer][Period.Ahead].Add(products[i]); 
    dict[emailID][Roles.Preparer][Period.Past].Add(products[i]); 
    dict[emailID][Roles.Approver][Period.Past].Add(products[i]); 
    dict[emailID][Roles.Approver][Period.Ahead].Add(products[i]); 
} 

然後你可以使用類似的代碼來獲取項目。給定一個電子郵件ID,下面會「之前提前過去」讓你在訂購的項目清單以「編制人之前批准」和:

List<Product> productsForEMailID = new List<Product>(); 

productsForEMailID.AddRange(dict[emailID][Roles.Preparer][Period.Past]); 
productsForEMailID.AddRange(dict[emailID][Roles.Approver][Period.Past]); 
productsForEMailID.AddRange(dict[emailID][Roles.Preparer][Period.Ahead]); 
productsForEMailID.AddRange(dict[emailID][Roles.Approver][Period.Ahead]); 

的產品是「分類」列表。

+1

爲什麼downvote? –

+0

理解。最外面的字典包含一次「Sachin」。相應的值是一個帶有「Roles.Preparer」和「Roles.Approver」鍵的字典。這些反過來又包含字典......沒有重複的鍵。 – Rawling

+0

是的。否則,他不會希望按「週期」進行排序。 –

0

你可以使用另一種類型的密鑰,更適合於這個問題。如果你想爲一個SortedDictionary<string, List<Product>>快速劈:

"Sachin#0#0" --> Products 
"Sachin#0#1" --> Products 
... 

在這裏,我認爲以「#」字符不能在名稱中出現。第一個數字代表RolesPreparer = 0Approver = 1,而第二個數字代表PeriodAhead = 0Past = 1

或者 - 如果你需要一個稍微強大的解決方案,我會做這樣的:

public struct Key : IComparable<Key> 
{ 
    public String Name; 
    public Roles Role; 
    public Period Period; 

    public int CompareTo(Key other) 
    { 
     var c = String.Compare(Name, other.Name, StringComparison.Ordinal); 
     if (c != 0) return c; 
     c = Role.CompareTo(other.Role); 
     if (c != 0) return c; 
     return Period.CompareTo(other.Period); 
    } 
} 

...並使用SortedDictionary<Key, List<Product>>