我经常需要根据值对字典(由键和值组成)进行排序。例如,我有一个单词和相应频率的散列,我想按频率排序。
有一个SortedList,它适用于单个值(比如频率),我想把它映射回单词。
SortedDictionary按键排序,而不是按值。有些人求助于自定义课程,但有没有更干净的方法呢?
我经常需要根据值对字典(由键和值组成)进行排序。例如,我有一个单词和相应频率的散列,我想按频率排序。
有一个SortedList,它适用于单个值(比如频率),我想把它映射回单词。
SortedDictionary按键排序,而不是按值。有些人求助于自定义课程,但有没有更干净的方法呢?
当前回答
在较高的层次上,您别无选择,只能遍历整个Dictionary并查看每个值。
也许这有帮助: 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);
}
);
其他回答
实际上在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更快,更面向对象。
环顾四周,使用一些c# 3.0特性,我们可以这样做:
foreach (KeyValuePair<string,int> item in keywordCounts.OrderBy(key=> key.Value))
{
// do something with item.Key and item.Value
}
这是我见过的最干净的方法,类似于Ruby处理散列的方法。
如果您想要的只是一个按值排序的“临时”列表,那么其他答案都很好。然而,如果你想让一个按Key排序的字典自动与另一个按Value排序的字典同步,你可以使用Bijection<K1, K2>类。
双射<K1, K2>允许您使用两个现有字典初始化集合,因此如果您希望其中一个字典是无序的,而另一个字典是有序的,您可以使用如下代码创建双射
var dict = new Bijection<Key, Value>(new Dictionary<Key,Value>(),
new SortedDictionary<Value,Key>());
您可以像使用任何普通字典一样使用dict(它实现了dicictionary <K, V>),然后调用dict。以获得“逆”字典,它是由值排序。
Bijection<K1, K2>是Loyc.Collections.dll的一部分,但如果您愿意,您可以简单地将源代码复制到您自己的项目中。
注意:如果有多个键具有相同的值,您不能使用双射,但您可以手动同步普通Dictionary<Key, value >和BMultiMap< value, Key>。
你可以按值对Dictionary进行排序并将其保存回自身(这样当你对它进行foreach时,值就会按顺序出来):
dict = dict.OrderBy(x => x.Value).ToDictionary(x => x.Key, x => x.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);
}