如何按值对字典进行排序?

我经常必须按值对字典(由键和值组成)进行排序。例如,我有一个单词和相应频率的哈希,我想按频率排序。

有一个SortedList对于单个值(比如频率)很有用,我想映射回单词。

分类字典按键排序,而不是按值排序。有些人求助于自定义类,但有没有更干净的方法?

759644 次浏览

环顾四周,使用一些C#3.0特性,我们可以做到这一点:

foreach (KeyValuePair<string,int> item in keywordCounts.OrderBy(key=> key.Value)){// do something with item.Key and item.Value}

这是我见过的最干净的方式,类似于Ruby处理哈希的方式。

在高层次上,您别无选择,只能浏览整个字典并查看每个值。

这可能有助于:http://bytes.com/forum/thread563638.html复制/粘贴来自John Timney:

Dictionary<string, string> s = new Dictionary<string, string>();s.Add("1", "a Item");s.Add("2", "c Item");s.Add("3", "b Item");
List<KeyValuePair<string, string>> myList = new List<KeyValuePair<string, string>>(s);myList.Sort(delegate(KeyValuePair<string, string> firstPair,KeyValuePair<string, string> nextPair){return firstPair.Value.CompareTo(nextPair.Value);});

用途:

using System.Linq.Enumerable;...List<KeyValuePair<string, string>> myList = aDictionary.ToList();
myList.Sort(delegate(KeyValuePair<string, string> pair1,KeyValuePair<string, string> pair2){return pair1.Value.CompareTo(pair2.Value);});

由于您的目标是. NET 2.0或更高版本,因此可以将其简化为lambda语法——它是等效的,但更短。如果您的目标是. NET 2.0,则只能在使用Visual Studio 2008(或更高版本)的编译器时使用此语法。

var myList = aDictionary.ToList();
myList.Sort((pair1,pair2) => pair1.Value.CompareTo(pair2.Value));

使用LINQ:

Dictionary<string, int> myDict = new Dictionary<string, int>();myDict.Add("one", 1);myDict.Add("four", 4);myDict.Add("two", 2);myDict.Add("three", 3);
var sortedDict = from entry in myDict orderby entry.Value ascending select entry;

这也将允许很大的灵活性,因为你可以选择前10名,20 10%等,或者如果你使用type-ahead的词频索引,你也可以包括StartsWith子句。

无论如何,你永远无法对字典进行排序。它们实际上并不是有序的。字典的保证是键和值集合是可迭代的,值可以通过索引或键检索,但不能保证任何特定的顺序。因此,您需要将名称值对放入列表中。

获取排序字典的最简单方法是使用内置的SortedDictionary类:

//Sorts sections according to the key value stored on "sections" unsorted dictionary, which is passed as a constructor argumentSystem.Collections.Generic.SortedDictionary<int, string> sortedSections = null;if (sections != null){sortedSections = new SortedDictionary<int, string>(sections);}

sortedSections将包含sections的排序版本

使用VB.NET对SortedDictionary列表进行排序以绑定到ListView控件:

Dim MyDictionary As SortedDictionary(Of String, MyDictionaryEntry)
MyDictionaryListView.ItemsSource = MyDictionary.Values.OrderByDescending(Function(entry) entry.MyValue)
Public Class MyDictionaryEntry ' Need Property for GridViewColumn DisplayMemberBindingPublic Property MyString As StringPublic Property MyValue As IntegerEnd Class

XAML:

<ListView Name="MyDictionaryListView"><ListView.View><GridView><GridViewColumn DisplayMemberBinding="{Binding Path=MyString}" Header="MyStringColumnName"></GridViewColumn><GridViewColumn DisplayMemberBinding="{Binding Path=MyValue}" Header="MyValueColumnName"></GridViewColumn></GridView></ListView.View></ListView>

或者为了好玩,你可以使用一些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));

您可以使用:

var ordered = dict.OrderBy(x => x.Value).ToDictionary(x => x.Key, x => x.Value);

您可以按值对字典进行排序并将其保存回自身(因此,当您对其进行preach时,值按顺序出现):

dict = dict.OrderBy(x => x.Value).ToDictionary(x => x.Key, x => x.Value);

当然,它可能不正确,但它有效。Hyrum定律意味着这很可能会继续工作。

您可以按值对字典进行排序,并使用以下代码在字典中获取结果:

Dictionary <<string, string>> ShareUserNewCopy =ShareUserCopy.OrderBy(x => x.Value).ToDictionary(pair => pair.Key,pair => pair.Value);

您不会对Dicpedia中的条目进行排序。. NET中的字典类是作为哈希表实现的-根据定义,此数据结构不可排序。

如果您需要能够迭代集合(按键)-您需要使用SortedDicpedia,它是作为二进制搜索树实现的。

然而,在你的情况下,源结构是无关紧要的,因为它是按不同的字段排序的。你仍然需要按频率对其进行排序,并将其放入按相关字段(频率)排序的新集合中。因此,在这个集合中,频率是键,单词是值。由于许多单词可以具有相同的频率(并且你将其用作键),因此既不能使用字典也不能使用SortedDicpedia(它们需要唯一的键)。这给你留下了一个SortedList。

我不明白你为什么坚持在你的主/第一个词典中保留一个指向原始项目的链接。

如果集合中的对象具有更复杂的结构(更多字段),并且您需要能够使用多个不同的字段作为键来有效地访问/排序它们-您可能需要一个自定义数据结构,该结构将包括支持O(1)插入和删除(LinkedList)的主存储器和多个索引结构-Dictionary/SortedDictionary/SortedList。这些索引将使用您复杂类中的一个字段作为键,并使用LinkedList中LinkedListNode的指针/引用作为值。

您需要协调插入和删除以保持索引与主集合(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);}

假设你有一个字典,你可以使用下面的一个衬里直接对它们进行排序:

var x = (from c in dict orderby c.Value.Order ascending select c).ToDictionary(c => c.Key, c=>c.Value);

假设我们有一个字典:

Dictionary<int, int> dict = new Dictionary<int, int>();dict.Add(21,1041);dict.Add(213, 1021);dict.Add(45, 1081);dict.Add(54, 1091);dict.Add(3425, 1061);dict.Add(768, 1011);

您可以使用临时字典将值存储为:

Dictionary<int, int> dctTemp = new Dictionary<int, int>();foreach (KeyValuePair<int, int> pair in dict.OrderBy(key => key.Value)){dctTemp.Add(pair.Key, pair.Value);}

您可以使用:

Dictionary<string, string> dic= new Dictionary<string, string>();var ordered = dic.OrderBy(x => x.Value);return ordered.ToDictionary(t => t.Key, t => t.Value);

如果您只想拥有一个按值排序的“临时”列表,那么其他答案都很好。然而,如果您想让一个按Key排序的字典与另一个按Value排序的字典一起按自动同步排序,您可以使用#2类

Bijection<K1, K2>允许您使用两个现有字典初始化集合,因此如果您希望其中一个未排序,而您希望另一个排序,您可以使用以下代码创建双射

var dict = new Bijection<Key, Value>(new Dictionary<Key,Value>(),new SortedDictionary<Value,Key>());

您可以像使用任何普通字典一样使用dict(它实现了IDictionary<K, V>),然后调用dict.Inverse来获取按Value排序的“逆”字典。

Bijection<K1, K2>Loyc.Collections.dll的一部分,但是如果你愿意,你可以简单地将源代码复制到你自己的项目中。

说明:如果有多个键具有相同的值,则不能使用Bijection,但可以手动在普通的Dictionary<Key,Value>BMultiMap<Value,Key>之间进行同步。

实际上,在C#中,字典没有sor()方法。由于你对按值排序更感兴趣,你不能得到值,直到你提供他们的关键。简而言之,您需要使用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);

或:

var sortedKeys = from pair in dictNameorderby pair.Value ascendingselect pair;

它还取决于您存储的值类型:单个(如string、int)或多个(如List、Array、用户定义的类)。如果它是单一的,你可以列出它,然后应用排序。
如果它是用户定义的类,那么该类必须实现ICompable,ClassName: IComparable<ClassName>和overrivecompareTo(ClassName c),因为它们比LINQ更快,更面向对象。

所需命名空间:using System.Linq;

Dictionary<string, int> counts = new Dictionary<string, int>();counts.Add("one", 1);counts.Add("four", 4);counts.Add("two", 2);counts.Add("three", 3);

按desc订购:

foreach (KeyValuePair<string, int> kvp in counts.OrderByDescending(key => key.Value)){// some processing logic for each item if you want.}

订阅关于Asc的评论:

foreach (KeyValuePair<string, int> kvp in counts.OrderBy(key => key.Value)){// some processing logic for each item if you want.}

排序和打印:

var items = from pair in players_Dicorderby pair.Value descendingselect pair;
// Display results.foreach (KeyValuePair<string, int> pair in items){Debug.Log(pair.Key + " - " + pair.Value);}

更改降序到加序以更改排序顺序

根据定义,字典是一种无序的关联结构,它以可散列的方式仅包含值和键。换句话说,没有预先可见的方式来排序字典。

参考阅读这篇文章从python语言。

链接python数据结构

最佳方式:

var list = dict.Values.OrderByDescending(x => x).ToList();var sortedData = dict.OrderBy(x => list.IndexOf(x.Value));