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

948

我经常需要对一个字典(包含键和值)按值进行排序。例如,我有一个单词和相应频率的哈希表,我想按频率排序。

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

SortedDictionary按键而不是值进行排序。一些人会使用自定义类,但是否有更简洁的方法呢?


2
除了仅仅对字典进行排序(如已接受的答案所述),您还可以创建一个IComparer来完成此操作(确实它接受要比较的键,但是有了键,您就可以获取值)。;-) - BrainSlugs83
3
“创建一个IComparer”并不是一个完整的解决方案。请说明如何使用该IComparer来产生排序结果。 - ToolmakerSteve
2
排序的字典没有意义,因为你是通过键来访问字典的。如果你想要一个按键和值排序的列表,请将其转换为列表,然后进行排序。 - Yarek T
你可以通过多种方式访问 yearek T,其中包括使用 ElementAt(int index) 方法。此外,你还可以使用 foreach 循环来按索引迭代。 - Barreto
22个回答

10

使用 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>

6
其他回答都不错,如果你只想有一个按值排序的“临时”列表。但是,如果你想要一个按Key排序的字典,并且自动与另一个按Value排序的字典同步,你可以使用Bijection<K1, K2>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> 之间手动同步。

类似于https://dev59.com/mHVC5IYBdhLWcg3whRcw,但可以将每个Dictionary替换为SortedDictionary。尽管答案似乎不支持重复值(假设1对1)。 - crokusek

6

实际上在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);

或者:

var sortedKeys = from pair in dictName
            orderby pair.Value ascending
            select pair;

这也取决于你要存储的值的类型:单个(如字符串、整数)还是多个(如List、Array、用户定义的类)。

如果它是单个的,你可以将它们放在列表中,然后应用排序。

如果是用户定义的类,则必须实现IComparable接口,例如:ClassName: IComparable<ClassName>,并重写compareTo(ClassName c)方法,因为这比LINQ更快且更面向对象。


3

需要使用的命名空间: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);

按照倒序排序:

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.
}

因为清晰使用了 OrderByDescending 而点赞。 - ToolmakerSteve

2

获取已排序的字典最简单的方法是使用内置的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 的排序版本。


11
正如您在评论中提到的那样,SortedDictionary 是按键排序的。而问题的提出者想要按值排序。在这种情况下,SortedDictionary 无法帮助解决问题。 - Marty Neal
好的…如果他/她(你)能够,请将值设置为键。我测试了操作时间,并发现sorteddictionary()总是比其他方法快至少1微秒,并且它更易于管理(因为将其转换回类似于Dictionary的易于交互和管理的形式的开销为0(它已经是一个sorteddictionary)。 - brandeded
7
@mbrownnyc - 不可以,这样做需要假设或前提条件,即数值是唯一的,但这并不保证。 - Roger Willcocks

2
假设我们有一个字典,如下所示:
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);
}

1
以下代码片段按值对字典进行排序。
代码首先创建一个字典,然后使用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);  
    }  
} 

1

排序并打印:

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);
}

将降序更改为升序以更改排序顺序


0

最佳方式:

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

0

字典的定义是一种无序的关联结构,只包含以可哈希方式存储的键和值。换句话说,字典没有可预测的排序方式。

有关详细信息,请阅读Python语言的这篇文章。

链接 Python数据结构


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接