我经常需要对字典进行排序,包括键和键。价值,按价值。例如,我有一个单词和各个频率的散列,我想按频率排序。
有一个SortedList
对单个值(比如频率)有好处,我想将它映射回单词。
SortedDictionary按键排序,而非价值。有些人诉诸custom class,但有更清洁的方式吗?
答案 0 :(得分:499)
使用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
条款也是如此。
答案 1 :(得分:498)
使用:
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));
答案 2 :(得分:212)
var ordered = dict.OrderBy(x => x.Value);
答案 3 :(得分:156)
环顾四周,使用一些C#3.0功能,我们可以做到这一点:
foreach (KeyValuePair<string,int> item in keywordCounts.OrderBy(key=> key.Value))
{
// do something with item.Key and item.Value
}
这是我见过的最干净的方式,类似于Ruby处理哈希的方式。
答案 4 :(得分:150)
您可以按值对字典进行排序并将其保存回自身(这样当您对其进行操作时,值会按顺序排出):
dict = dict.OrderBy(x => x.Value).ToDictionary(x => x.Key, x => x.Value);
当然,这可能不正确,但它确实有效。
答案 5 :(得分:58)
在较高的层面上,你没有别的选择可以浏览整个字典并查看每个值。
也许这会有所帮助: http://bytes.com/forum/thread563638.html 复制/粘贴约翰蒂姆尼:
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);
}
);
答案 6 :(得分:23)
无论如何,你永远无法对字典进行排序。他们实际上没有订购。字典的保证是键和值集合是可迭代的,并且可以通过索引或键检索值,但不保证任何特定的顺序。因此,您需要将名称值对放入列表中。
答案 7 :(得分:16)
您不对词典中的条目进行排序。 .NET中的字典类是作为哈希表实现的 - 根据定义,这种数据结构不可排序。
如果你需要能够迭代你的集合(按键) - 你需要使用SortedDictionary,它实现为二进制搜索树。
在您的情况下,源结构无关紧要,因为它按不同的字段排序。您仍然需要按频率对其进行排序,并将其放入按相关字段(频率)排序的新集合中。所以在这个集合中,频率是键,单词是值。由于许多单词可以具有相同的频率(并且您将其用作键),因此您既不能使用Dictionary也不能使用SortedDictionary(它们需要唯一键)。这为您留下了SortedList。
我不明白为什么你坚持维护主/第一本词典中原始项目的链接。
如果集合中的对象具有更复杂的结构(更多字段),并且您需要能够使用几个不同的字段作为键来有效地访问/排序它们 - 您可能需要一个自定义数据结构,其中包含支持O(1)插入和删除(LinkedList)的主存储和几个索引结构--Dictionaries / SortedDictionaries / SortedLists。这些索引将使用复杂类中的一个字段作为键,并将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);
}
答案 8 :(得分:14)
Dictionary<string, string> dic= new Dictionary<string, string>();
var ordered = dic.OrderBy(x => x.Value);
return ordered.ToDictionary(t => t.Key, t => t.Value);
答案 9 :(得分:10)
排序值
这显示了如何对Dictionary中的值进行排序。我们看到一个可以在Visual Studio中编译并运行的控制台程序。它为Dictionary添加了键,然后按其值对它们进行排序。请记住,Dictionary实例最初不以任何方式排序。我们在查询语句中使用LINQ orderby关键字。
OrderBy条款 对Dictionary [C#]
进行排序的程序using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
// Example dictionary.
var dictionary = new Dictionary<string, int>(5);
dictionary.Add("cat", 1);
dictionary.Add("dog", 0);
dictionary.Add("mouse", 5);
dictionary.Add("eel", 3);
dictionary.Add("programmer", 2);
// Order by values.
// ... Use LINQ to specify sorting by value.
var items = from pair in dictionary
orderby pair.Value ascending
select pair;
// Display results.
foreach (KeyValuePair<string, int> pair in items)
{
Console.WriteLine("{0}: {1}", pair.Key, pair.Value);
}
// Reverse sort.
// ... Can be looped over in the same way as above.
items = from pair in dictionary
orderby pair.Value descending
select pair;
}
}
输出
dog: 0
cat: 1
programmer: 2
eel: 3
mouse: 5
答案 10 :(得分:10)
或者为了好玩,你可以使用一些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));
答案 11 :(得分:9)
使用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 DisplayMemberBinding
Public Property MyString As String
Public Property MyValue As Integer
End 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>
答案 12 :(得分:5)
获取已排序字典的最简单方法是使用内置的SortedDictionary
类:
//Sorts sections according to the key value stored on "sections" unsorted dictionary, which is passed as a constructor argument
System.Collections.Generic.SortedDictionary<int, string> sortedSections = null;
if (sections != null)
{
sortedSections = new SortedDictionary<int, string>(sections);
}
sortedSections
将包含sections
答案 13 :(得分:5)
其他答案都很好,如果你想要的只是一个&#34;临时&#34;列表按值排序。但是,如果您希望按Key
排序自动同步与另一个按Value
排序的字典的字典,则可以使用Bijection<K1, K2>
class。< / p>
Bijection<K1, K2>
允许您使用两个现有字典初始化集合,因此如果您希望其中一个字典未排序,并且您希望对另一个字典进行排序,则可以使用
var dict = new Bijection<Key, Value>(new Dictionary<Key,Value>(),
new SortedDictionary<Value,Key>());
您可以像任何普通字典一样使用dict
(它实现IDictionary<K, V>
),然后调用dict.Inverse
以获得&#34;反向&#34;按Value
排序的字典。
Bijection<K1, K2>
是Loyc.Collections.dll的一部分,但如果您愿意,可以将source code复制到您自己的项目中。
注意:如果有多个键具有相同的值,则您无法使用Bijection
,但您可以在普通Dictionary<Key,Value>
之间手动同步一个BMultiMap<Value,Key>
。
答案 14 :(得分:3)
假设我们有一个字典
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);
sict.Add(768, 1011);
1)您可以使用 temporary dictionary to store values as
:
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);
}
答案 15 :(得分:0)
实际上,在C#中,字典dint具有sort()方法, 因为您对按值排序更感兴趣, 您必须先提供值,才能获得价值, 简而言之,您需要遍历它们, 使用LINQ的Order By,
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 dictName
orderby pair.Value ascending
select pair;
它还取决于您存储的是哪种值,
它是单个(如字符串,int)还是多个(如List,Array,用户定义的类),
如果是单身,则可以列出清单,然后进行排序。
如果是用户定义的类,
那么该类必须实现IComparable,
ClassName: IComparable<ClassName>
并覆盖compareTo(ClassName c)
因为它们比LINQ更快,并且更面向对象。
答案 16 :(得分:0)
所需的名称空间: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.
}
按升序排列:
foreach (KeyValuePair<string, int> kvp in counts.OrderBy(key => key.Value))
{
// some processing logic for each item if you want.
}
答案 17 :(得分:0)
排序并打印:
var items = from pair in players_Dic
orderby pair.Value descending
select pair;
// Display results.
foreach (KeyValuePair<string, int> pair in items)
{
Debug.Log(pair.Key + " - " + pair.Value);
}
更改降序以更改排序顺序
答案 18 :(得分:-2)
您可以按值对Dictionary进行排序,并使用以下代码在字典中获取结果:
Dictionary <<string, string>> ShareUserNewCopy =
ShareUserCopy.OrderBy(x => x.Value).ToDictionary(pair => pair.Key,
pair => pair.Value);
答案 19 :(得分:-2)
鉴于你有一本词典,你可以使用下面的一个班轮直接对它们进行排序:
var x = (from c in dict orderby c.Value.Order ascending select c).ToDictionary(c => c.Key, c=>c.Value);