赞
踩
我有一本C语言的字典
Dictionary
我想把字典按照键(class person中的一个字段)进行排序。我该怎么做?互联网上所有可用的帮助都是列表帮助,没有特定的字典就地排序示例。任何帮助都将不胜感激!
我不确定我理解你的问题,因为字典没有按任何顺序列举?您可以迭代键或值,这些键或值可以很容易地动态排序…
这不可能是你真正想要的。数组可以就地排序,因为对数组排序的结果是一个数组。但是字典不是数组,因此不能用对其条目排序的结果替换它。排序条目并将结果保存到数组或列表中。接受的答案可能不是你想要的…从SortedList或SortedDictionary输入和访问条目比从字典输入和访问条目慢得多。
你不能对一个Dictionary进行排序——它本质上是无序的。(或者更确切地说,条目的检索顺序是特定于实现的。您不应该以相同的方式在版本之间工作,因为排序不是其设计功能的一部分。)
您可以使用SortedList或SortedDictionary,这两种类型都是按键排序的(以可配置的方式,如果您将IEqualityComparer传递到构造函数中),这些可能对您有用吗?
很少注意名称SortedList中的单词"list"——它仍然是一个字典,因为它将键映射到值。它是在内部使用一个列表来实现的,非常有效——因此,它不使用哈希代码进行查找,而是进行二进制搜索。SortedDictionary同样基于二进制搜索,但通过树而不是列表。
但是,要小心使用SortedList:如果构建一个大的列表(假设项目不是预先排序的),它将非常慢。通常您应该使用SortedDictionary来代替,或者使用第三方BDictionary来获得与SortedDictionary类似的性能,而不会丢失按索引或"查找最近的键"访问项目的能力。
二进制搜索的优势是什么,而不是在排序的键旁边维护哈希?如果我不是只做有序的枚举,为什么我关心元素是有序的?如果我更关心单个元素的查找,但第二种情况是想根据键顺序进行枚举,那么我是不是一直在管理一个单独的键列表,一个La Steve的答案?如果这是我的理想用途,那么SortedList和SortedDictionary实际上是错误的工具,对吗?也就是说,如果我真的只想在适当的位置对字典键进行排序呢?
@鲁芬:优势在于避免复杂性。是的,据我所知,没有内置的"排序和散列"集合。注意,这样的集合很难使用,也很难构建——必须同时提供相等比较、哈希代码函数以及排序函数。当然,保存这两个集合也需要一定的内存成本。您需要测量二进制搜索与散列查询的成本,以查找实际数据——您很可能会发现,除非您的收集量很大,否则它实际上并不重要。
@Ruffin"二进制搜索的优点是什么,而不是在排序键旁边维护哈希?"--哈希表的内存以及添加或删除条目时维护它的时间。"为什么我关心元素的顺序呢?——如果你不关心元素的顺序,那么就使用字典(我通常建议使用SortedList或SortedDictionary),但第二种方法是根据键顺序进行枚举——当你偶尔需要时,对枚举的键值对进行排序是很简单的:dict.orderby(kV= kV键
@Ruffin"如果我真的只想在适当的位置对字典键进行排序怎么办?"--没有这样的事情——这是一个类别错误。数组可以就地排序…任何不是数组的东西都不能。(好吧,除了具有可变节点的链表,但是在适当的位置对这样的东西进行排序是非常困难和昂贵的。)但是当然,您可以做一些类似于var array = dict.Keys.ToArray(); array.Sort();的事情。
@拉芬:"我是不是一直在管理一个单独的钥匙列表,一个拉斯蒂夫的答案?"--他的答案中没有"单独的钥匙列表"…只是dict.Keys…尽管通常通过,比如说,dict.OrderBy(kv => kv.Key)对keyValuePairs进行操作比较好。
尝试使用SortedDictionary
你的回答比上帝慢了21秒。还不错。
正确的答案已经说明(只使用sorteddictionary)。
但是,如果您偶然需要将集合保留为字典,则可以按顺序访问字典键,例如,通过对列表中的键进行排序,然后使用此列表访问字典。一个例子…
Dictionary dupcheck = new Dictionary();
…一些填充"dupcheck"的代码,然后…
if (dupcheck.Count > 0) {
Console.WriteLine("
dupcheck (count: {0})
----", dupcheck.Count);
var keys_sorted = dupcheck.Keys.ToList();
keys_sorted.Sort();
foreach (var k in keys_sorted) {
Console.WriteLine("{0} = {1}", k, dupcheck[k]);
}
}
别忘了这件事。
"如果您偶然需要将集合保留为字典"--保留它的明显原因是它的插入、删除和查找速度更快。至于var keys_sorted = dupcheck.Keys.ToList(); keys_sorted.Sort();——更简单的是keys_sorted = dupcheck.Keys.OrderBy(k => k).ToList();…如果要使用这些值,那么只需foreach (var ent in dupcheck.OrderBy(kv => kv.Key)) Console.WriteLine($"{ent.Key} = {ent.Value}");
按设计,字典是不可排序的。如果您在字典中需要此功能,请查看SortedDictionary。
看看SortedDictionary,甚至还有一个构造函数重载,这样您就可以传入自己的IComparable进行比较。
当字典实现为哈希表时,SortedDictionary实现为红黑树。
如果不利用算法中的顺序,只需要在输出前对数据进行排序,那么使用sortedDictionary将对性能产生负面影响。
您可以这样"排序"字典:
Dictionary dictionary = new Dictionary();
// algorithm
return new SortedDictionary(dictionary);
如果要按键对条目进行排序,只需使用dictionary.OrderBy(kv => kv.Key)。
由于这个答案的高搜索位置,我认为Linq Orderby解决方案值得展示:
class Person
{
public Person(string firstname, string lastname)
{
FirstName = firstname;
LastName = lastname;
}
public string FirstName { get; set; }
public string LastName { get; set; }
}
static void Main(string[] args)
{
Dictionary People = new Dictionary();
People.Add(new Person("John","Doe"), 1);
People.Add(new Person("Mary","Poe"), 2);
People.Add(new Person("Richard","Roe"), 3);
People.Add(new Person("Anne","Roe"), 4);
People.Add(new Person("Mark","Moe"), 5);
People.Add(new Person("Larry","Loe"), 6);
People.Add(new Person("Jane","Doe"), 7);
foreach (KeyValuePair person in People.OrderBy(i => i.Key.LastName))
{
Debug.WriteLine(person.Key.LastName +"," + person.Key.FirstName +" - Id:" + person.Value.ToString());
}
}
输出:
Doe, John - Id: 1
Doe, Jane - Id: 7
Loe, Larry - Id: 6
Moe, Mark - Id: 5
Poe, Mary - Id: 2
Roe, Richard - Id: 3
Roe, Anne - Id: 4
在本例中,对名字也使用thenby是有意义的:
foreach (KeyValuePair person in People.OrderBy(i => i.Key.LastName).ThenBy(i => i.Key.FirstName))
则输出为:
Doe, Jane - Id: 7
Doe, John - Id: 1
Loe, Larry - Id: 6
Moe, Mark - Id: 5
Poe, Mary - Id: 2
Roe, Anne - Id: 4
Roe, Richard - Id: 3
对于需要它的人,Linq还具有orderByDescending和ByDescending。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。