2013-01-21 147 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>>