【问题标题】:C# iterating over Dictionary by arbitrary orderC# 按任意顺序迭代字典
【发布时间】:2015-09-15 13:15:36
【问题描述】:

我有一个Dictionary<string, List<Object>>。我遍历字典的键并显示按键分组的值。我知道 SortedDictionary 和 OrderedDictionary,但是如何按预定义的顺序对字典进行排序,而不仅仅是按字母升序/降序?

假设我知道我的字典中所有可能的键都将存在于以下列表中,并希望字典按以下顺序排序:

  1. 快速
  2. 棕色
  3. 狐狸
  4. 跳了
  5. 结束

我该怎么做?

【问题讨论】:

  • 创建字典实例时可以使用SortedDictionary<string, List<Object>>并提供IComparer<String>
  • 没有任何逻辑可以为您提供该命令。无论您如何实施它,您都必须自己“挑选”订单。
  • 排序和任意顺序是互斥的。 “排序”是指对象之间存在一定的关系。排序是对容器中的对象重新排序以满足这些条件。

标签: c# sorting dictionary


【解决方案1】:

您根本不会对Dictionary<,> 进行排序。但是,如果您想以特定顺序迭代条目(或键),您可以使用 LINQ 的OrderBy - 并按该顺序迭代一组已知的值,您可以将有序集放在其他地方。例如:

string[] orderedKeys = { "Quick", "Brown", "Fox", "Jumped", "Over" };
var orderedPairs = dictionary.OrderBy(pair => orderedKeys.IndexOf(pair.Key));
foreach (var pair in orderedPairs)
{
    // Use pair.Key and pair.Value here
}

【讨论】:

  • 为什么不直接遍历 orderedKeys 并直接访问字典值?
  • @juharr:这是另一种选择,是的 - 您需要注意不要访问不存在的密钥,并且您不会拿起任何您不知道的密钥大约提前。
  • 当然,您的订单会将任何未知键放在开头,因为IndexOf 将返回-1。
  • @juharr:确实。不过,如果 OP 想要别的东西,那将很容易解决。
【解决方案2】:

如果您想始终按该顺序访问键/值对并从SortedDictionary 中受益,您需要实现IComparer<string> 并将其传递给您的字典构造函数。实现它的最简单方法是按您想要的顺序拥有一个静态字符串数组,然后比较两个字符串的索引:

public class MyStringComparer : IComparer<string>
{

   static string[] StringsInOrder = new [] { "Quick", "Brown", "Fox", "Jumped", "Over" };
   public int Compare(string s1, string s2)
    {
        // find the indexes of the strings in the desired sort order
        int i1 = Array.IndexOf(StringsInOrder, s1);
        int i2 = Array.IndexOf(StringsInOrder, s2);

        if(i1 < 0)
            // put at the end in alpha order
            if(i2 < 0)
                return s1.CompareTo(s2);
            else  
                // send s1 to the end
                return 1;  
        else
           if(i2 < 0)
               // send s2 to the end
               return -1;
           else  
                // compare the indices in the array
                return i1.CompareTo(i2);
    }
}

用法:

var d = new SortedDictionary<string, string> (new MyStringComparer());

如果您想保留普通字典以用于其他目的(快速查找等),但只是偶尔对键进行排序,那么整体上使用 Jon 建议的 Linq 可能会更好。

【讨论】:

    【解决方案3】:

    只是一个想法。您能否将“SortKey”属性添加到您的对象并使用 LINQ 获取排序列表?

    【讨论】:

      【解决方案4】:

      一种选择是迭代键列表并访问字典中的值。

      string[] orderedKeys = { "Quick", "Brown", "Fox", "Jumped", "Over" };
      foreach (var key in orderedKeys)
      {
          List<object> values;
          if (dictionary.TryGetValue(key, out values))
          {
              // Here you have the key and the list of values
          }
          else
          {
              // The key was not in the dictionary.
          }
      }
      

      请注意,这不会为您提供字典中没有列表中相应键的任何条目。如果列表有重复项,它也可能会为您提供两次条目。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-11-25
        • 2012-12-09
        • 1970-01-01
        • 1970-01-01
        • 2013-10-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多