按照数组列表中的顺序按关键字对字典进行排序

本文关键字:字典 排序 关键字 顺序 数组 列表 | 更新日期: 2023-09-27 17:59:49

在一次采访中,我被问到以下问题。如何按照数组列表中的顺序按关键字对字典进行排序。

例如,我有一本字典如下

Dictionary<string, string> stringDict = new Dictionary<string, string>();
stringDict.Add("1", "One");
stringDict.Add("7", "Seven");
stringDict.Add("6", "Six");
stringDict.Add("2", "Two");
stringDict.Add("3", "Three");
stringDict.Add("5", "Five");
stringDict.Add("4", "Four");

数组列表如下

ArrayList stringArList = new ArrayList();
stringArList.Add("1");
stringArList.Add("2");
stringArList.Add("3");
stringArList.Add("5");
stringArList.Add("6");
stringArList.Add("7");
stringArList.Add("4");

如何按字典在数组列表中的顺序对其进行排序?

按照数组列表中的顺序按关键字对字典进行排序

你不能对字典本身进行排序,但你可以将键值对提取为列表,并对那些进行排序:

IEnumerable<KeyValuePair<string, string>> pairs = 
    stringDict.OrderBy(kvp => stringArList.IndexOf(kvp.Key));

但是,没有办法以任何特定的顺序"遍历"字典项。

您可以创建SortedDictionary并提供IComparer<string>

var d = new SortedDictionary<string, string>(stringDict, 
                                        new PositionComparer(stringArList));

Comparer实现为:

public class PositionComparer : IComparer<string>
{
   private ArrayList Keys {get; set;}
   public PositionComparer(ArrayList keys)
   {
       Keys = keys;
   }
   public int Compare(string s1, string s2)
   {
       return Keys.IndexOf(s1).CompareTo(Keys.IndexOf(s2));
   }
}

这将生成一个按需要排序的值列表。

var sortedValues = stringDict.OrderBy(pair => stringArList.IndexOf(pair.Key))
                             .Select(pair => pair.Value)
                             .ToList();

正如前面在这个问题中多次提到的,C#Dictionary无法排序。这是实施过程中固有的。正如您在这里所读到的,字典是使用哈希表实现的。这意味着这些商品没有任何订单。你不能说"把这本字典的第一个元素给我"。根本没有第一个、第二个或最后一个元素。关于字典中的元素,你只能说它有一个唯一的标识符,这个标识符决定了它在字典中的位置(通过散列函数的一点帮助)。

例如,当array中有一个元素时,可以说"这个元素是下一个元素"或"这个元素就是上一个元素。"。数组中的每个元素都有上一个和下一个。这不适用于词典。

当你在字典中插入一个条目时,它会根据关键字生成一个散列(一个相当唯一的数字)。例如,由名称组成的密钥的一个非常简单(而且很糟糕)的散列是将每个字符的总和作为名称中的ASCII值,然后将它们相加。结果是一个数字,比如5,然后我们将该值插入位置5的存储(例如数组)中。但是,如果位置5是另一个值,恰好具有相同的散列结果,则您有一个collision。如何解决这些问题,以及如何避免这些问题,就是哈希表的全部内容。有关此方面的详细信息,请参阅Wiki。

当您使用密钥someName请求您的值时,它会对该值进行散列并在该位置查找它。

哈希表并不像我刚才解释的那么简单,它也有很多。你可以在Wiki上阅读更多。

因此,"对这个字典排序"的答案肯定是"不可以。"。但是,你可以将它转换为一个可排序的数据结构,比如列表,或者其他什么,然后对它进行排序。

我回答了以下问题。

  var list = from arElement in stringArList.ToArray().ToList()
                   join dict in stringDict on arElement equals dict.Key 
                   select dict ;

但面试官似乎对此不以为然。

original_dic.OrderBy返回IOrderedEnumerable,您可以将其转换为新字典。

var ordered_dic = original_dic.OrderBy(x => x.Key).ToDictionary(x=> x.Key, x=> x.Value);