我经常需要根据值对字典(由键和值组成)进行排序。例如,我有一个单词和相应频率的散列,我想按频率排序。
有一个SortedList,它适用于单个值(比如频率),我想把它映射回单词。
SortedDictionary按键排序,而不是按值。有些人求助于自定义课程,但有没有更干净的方法呢?
我经常需要根据值对字典(由键和值组成)进行排序。例如,我有一个单词和相应频率的散列,我想按频率排序。
有一个SortedList,它适用于单个值(比如频率),我想把它映射回单词。
SortedDictionary按键排序,而不是按值。有些人求助于自定义课程,但有没有更干净的方法呢?
当前回答
下面的代码片段按值对Dictionary进行排序。
代码首先创建一个字典,然后使用OrderBy方法对条目进行排序。
public void SortDictionary()
{
// Create a dictionary with string key and Int16 value pair
Dictionary<string, Int16> AuthorList = new Dictionary<string, Int16>();
AuthorList.Add("Mahesh Chand", 35);
AuthorList.Add("Mike Gold", 25);
AuthorList.Add("Praveen Kumar", 29);
AuthorList.Add("Raj Beniwal", 21);
AuthorList.Add("Dinesh Beniwal", 84);
// Sorted by Value
Console.WriteLine("Sorted by Value");
Console.WriteLine("=============");
foreach (KeyValuePair<string, Int16> author in AuthorList.OrderBy(key => key.Value))
{
Console.WriteLine("Key: {0}, Value: {1}", author.Key, author.Value);
}
}
其他回答
您不需要对Dictionary中的条目进行排序。. net中的Dictionary类是作为哈希表实现的——这个数据结构在定义上是不可排序的。
如果你需要能够遍历你的集合(按键)-你需要使用SortedDictionary,它被实现为二叉搜索树。
然而,在您的例子中,源结构是不相关的,因为它是根据不同的字段排序的。您仍然需要按频率对其进行排序,并将其放入按相关字段(频率)排序的新集合中。在这个集合中,频率是键,单词是值。由于许多单词可以具有相同的频率(并且您将使用它作为键),因此不能既使用Dictionary也使用SortedDictionary(它们需要惟一的键)。这将留给您一个SortedList。
我不明白为什么你坚持在你的主/第一个字典中保持一个到原始条目的链接。
If the objects in your collection had a more complex structure (more fields) and you needed to be able to efficiently access/sort them using several different fields as keys - You would probably need a custom data structure that would consist of the main storage that supports O(1) insertion and removal (LinkedList) and several indexing structures - Dictionaries/SortedDictionaries/SortedLists. These indexes would use one of the fields from your complex class as a key and a pointer/reference to the LinkedListNode in the LinkedList as a value.
你需要协调插入和删除,以保持你的索引与主集合(LinkedList)同步,我认为删除将是相当昂贵的。 这与数据库索引的工作原理类似——它们非常适合查找,但当您需要执行许多插入和删除操作时,它们会成为负担。
只有当您要进行一些繁重的查找处理时,以上所有方法才有意义。如果你只需要输出一次按频率排序,那么你可以只生成一个(匿名)元组列表:
var dict = new SortedDictionary<string, int>();
// ToDo: populate dict
var output = dict.OrderBy(e => e.Value).Select(e => new {frequency = e.Value, word = e.Key}).ToList();
foreach (var entry in output)
{
Console.WriteLine("frequency:{0}, word: {1}",entry.frequency,entry.word);
}
或者为了好玩,你可以使用一些LINQ扩展的优点:
var dictionary = new Dictionary<string, int> { { "c", 3 }, { "a", 1 }, { "b", 2 } };
dictionary.OrderBy(x => x.Value)
.ForEach(x => Console.WriteLine("{0}={1}", x.Key,x.Value));
字典根据定义是一种无序的关联结构,仅以可哈希的方式包含值和键。换句话说,没有一种可预见的方式来排序一本字典。
作为参考,请阅读这篇来自python语言的文章。
链接 Python数据结构
实际上在c#中,字典没有sort()方法。 如果你对按值排序更感兴趣, 在为值提供键之前,您无法获取值。 简而言之,你需要使用LINQ的OrderBy()迭代它们,
var items = new Dictionary<string, int>();
items.Add("cat", 0);
items.Add("dog", 20);
items.Add("bear", 100);
items.Add("lion", 50);
// Call OrderBy() method here on each item and provide them the IDs.
foreach (var item in items.OrderBy(k => k.Key))
{
Console.WriteLine(item);// items are in sorted order
}
你可以做一个小技巧:
var sortedDictByOrder = items.OrderBy(v => v.Value);
or:
var sortedKeys = from pair in dictName
orderby pair.Value ascending
select pair;
这也取决于你存储的是什么类型的值:单个(如字符串,int)或多个(如列表,数组,用户定义的类)。 如果它是单个的,你可以把它列出来,然后应用排序。 如果它是用户定义的类,那么该类必须实现IComparable, ClassName: IComparable<ClassName>并覆盖compareTo(ClassName c),因为它们比LINQ更快,更面向对象。
你可以按值对Dictionary进行排序,并使用下面的代码在Dictionary中获取结果:
Dictionary <<string, string>> ShareUserNewCopy =
ShareUserCopy.OrderBy(x => x.Value).ToDictionary(pair => pair.Key,
pair => pair.Value);