简体   繁体   English

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

[英]How do you sort a dictionary by value?

I often have to sort a dictionary (consisting of keys & values) by value.我经常需要按值对字典(由键和值组成)进行排序。 For example, I have a hash of words and respective frequencies that I want to order by frequency.例如,我有一个 hash 的单词和我想按频率排序的相应频率。

There is a SortedList which is good for a single value (say frequency), that I want to map back to the word.有一个SortedList适用于单个值(比如频率),我想 map 回到这个词。

SortedDictionary orders by key, not value. SortedDictionary按键而不是值排序。 Some resort to a custom class , but is there a cleaner way?有些人求助于自定义 class ,但是有更简洁的方法吗?

Use LINQ:使用 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;

This would also allow for great flexibility in that you can select the top 10, 20 10%, etc. Or if you are using your word frequency index for type-ahead , you could also include StartsWith clause as well.这也将提供很大的灵活性,因为您可以选择前 10、20 10% 等。或者,如果您将词频索引用于type-ahead ,您也可以包括StartsWith子句。

Use:利用:

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

Since you're targeting .NET 2.0 or above, you can simplify this into lambda syntax -- it's equivalent, but shorter.由于您的目标是 .NET 2.0 或更高版本,因此您可以将其简化为 lambda 语法——它是等效的,但更短。 If you're targeting .NET 2.0 you can only use this syntax if you're using the compiler from Visual Studio 2008 (or above).如果您的目标是 .NET 2.0,则只能在使用 Visual Studio 2008(或更高版本)的编译器时使用此语法。

var myList = aDictionary.ToList();

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

你可以使用:

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

Looking around, and using some C# 3.0 features we can do this:环顾四周,并使用一些 C# 3.0 特性,我们可以做到这一点:

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

This is the cleanest way I've seen and is similar to the Ruby way of handling hashes.这是我见过的最干净的方式,类似于 Ruby 处理哈希的方式。

You can sort a Dictionary by value and save it back to itself (so that when you foreach over it the values come out in order):您可以按值对字典进行排序并将其保存回自身(这样当您对它进行 foreach 时,值会按顺序出现):

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

Sure, it may not be correct, but it works.当然,它可能不正确,但它确实有效。 Hyrum's Law means that this will very likely continue to work.海仑定律意味着这很可能会继续有效。

On a high level, you have no other choice than to walk through the whole Dictionary and look at each value.在高层次上,除了浏览整个字典并查看每个值之外,您别无选择。

Maybe this helps: http://bytes.com/forum/thread563638.html Copy/Pasting from John Timney:也许这会有所帮助: 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);
    }
);

You'd never be able to sort a dictionary anyway.无论如何,您永远无法对字典进行排序。 They are not actually ordered.它们实际上没有被订购。 The guarantees for a dictionary are that the key and value collections are iterable, and values can be retrieved by index or key, but there is no guarantee of any particular order.字典的保证是键和值集合是可迭代的,并且可以通过索引或键检索值,但不能保证任何特定的顺序。 Hence you would need to get the name value pair into a list.因此,您需要将名称值对放入列表中。

You do not sort entries in the Dictionary.您不对 Dictionary 中的条目进行排序。 Dictionary class in .NET is implemented as a hashtable - this data structure is not sortable by definition. .NET 中的字典类被实现为一个哈希表——这个数据结构根据定义是不可排序的。

If you need to be able to iterate over your collection (by key) - you need to use SortedDictionary, which is implemented as a Binary Search Tree.如果您需要能够迭代您的集合(按键) - 您需要使用 SortedDictionary,它被实现为二叉搜索树。

In your case, however the source structure is irrelevant, because it is sorted by a different field.但是,在您的情况下,源结构无关紧要,因为它是按不同的字段排序的。 You would still need to sort it by frequency and put it in a new collection sorted by the relevant field (frequency).您仍然需要按频率对其进行排序,并将其放入按相关字段(频率)排序的新集合中。 So in this collection the frequencies are keys and words are values.所以在这个集合中,频率是键,词是值。 Since many words can have the same frequency (and you are going to use it as a key) you cannot use neither Dictionary nor SortedDictionary (they require unique keys).由于许多单词可以具有相同的频率(并且您将使用它作为键),因此您既不能使用 Dictionary 也不能使用 SortedDictionary(它们需要唯一的键)。 This leaves you with a SortedList.这为您留下了一个 SortedList。

I don't understand why you insist on maintaining a link to the original item in your main/first dictionary.我不明白您为什么坚持在主/第一本词典中维护指向原始项目的链接。

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.如果您的集合中的对象具有更复杂的结构(更多字段),并且您需要能够使用几个不同的字段作为键来有效地访问/排序它们 - 您可能需要一个自定义数据结构,该结构将由主存储组成支持 O(1) 插入和删除 (LinkedList) 和几个索引结构 - 字典/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 中的 LinkedListNode 的指针/引用作为值。

You would need to coordinate insertions and removals to keep your indexes in sync with the main collection (LinkedList) and removals would be pretty expensive I'd think.您需要协调插入和删除以使索引与主集合(LinkedList)保持同步,并且我认为删除会非常昂贵。 This is similar to how database indexes work - they are fantastic for lookups but they become a burden when you need to perform many insetions and deletions.这类似于数据库索引的工作方式——它们非常适合查找,但当您需要执行许多插入和删除时,它们就会成为负担。

All of the above is only justified if you are going to do some look-up heavy processing.只有当您要进行一些查找繁重的处理时,上述所有内容才是合理的。 If you only need to output them once sorted by frequency then you could just produce a list of (anonymous) tuples:如果您只需要在按频率排序后输出它们,那么您可以只生成一个(匿名)元组列表:

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

You could use:你可以使用:

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

Or for fun you could use some LINQ extension goodness:或者为了好玩,您可以使用一些 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));

Sort values 排序值

This show how to sort the values in a Dictionary. 这显示了如何对Dictionary中的值进行排序。 We see a console program you can compile in Visual Studio and run. 我们看到一个可以在Visual Studio中编译并运行的控制台程序。 It adds keys to a Dictionary and then sorts them by their values. 它为Dictionary添加了键,然后按其值对它们进行排序。 Remember that Dictionary instances are not initially sorted in any way. 请记住,Dictionary实例最初不以任何方式排序。 We use the LINQ orderby keyword in a query statement. 我们在查询语句中使用LINQ orderby关键字。

OrderBy Clause Program that sorts Dictionary [C#] 对字典[C#]进行排序的OrderBy子句程序

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

Output 产量

dog: 0
cat: 1
programmer: 2
eel: 3
mouse: 5

Sorting a SortedDictionary list to bind into a ListView control using VB.NET:使用 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: 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>

The other answers are good, if all you want is to have a "temporary" list sorted by Value.如果您只想拥有一个按值排序的“临时”列表,那么其他答案也很好。 However, if you want to have a dictionary sorted by Key that automatically synchronizes with another dictionary that is sorted by Value , you could use the Bijection<K1, K2> class .但是,如果您想让一个按Key排序的字典自动与另一个按Value排序的字典同步,您可以使用Bijection<K1, K2>

Bijection<K1, K2> allows you to initialize the collection with two existing dictionaries, so if you want one of them to be unsorted, and you want the other one to be sorted, you could create your bijection with code like Bijection<K1, K2>允许您使用两个现有字典来初始化集合,因此如果您希望其中一个未排序,并且希望另一个排序,您可以使用如下代码创建双射

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

You can use dict like any normal dictionary (it implements IDictionary<K, V> ), and then call dict.Inverse to get the "inverse" dictionary which is sorted by Value .您可以像使用任何普通字典一样使用dict (它实现IDictionary<K, V> ),然后调用dict.Inverse来获取按Value排序的“逆”字典。

Bijection<K1, K2> is part of Loyc.Collections.dll , but if you want, you could simply copy the source code into your own project. Bijection<K1, K2>Loyc.Collections.dll的一部分,但如果您愿意,您可以简单地将源代码复制到您自己的项目中。

Note : In case there are multiple keys with the same value, you can't use Bijection , but you could manually synchronize between an ordinary Dictionary<Key,Value> and a BMultiMap<Value,Key> .注意:如果有多个具有相同值的键,则不能使用Bijection ,但可以在普通Dictionary<Key,Value>BMultiMap<Value,Key>之间手动同步。

Actually in C#, dictionaries don't have sort() methods.实际上在 C# 中,字典没有 sort() 方法。 As you are more interested in sort by values, you can't get values until you provide them key.由于您对按值排序更感兴趣,因此在为它们提供键之前,您无法获取值。 In short, you need to iterate through them using LINQ's OrderBy() ,简而言之,您需要使用 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
}

You can do one trick:你可以做一个技巧:

var sortedDictByOrder = items.OrderBy(v => v.Value);

or:或者:

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

It also depends on what kind of values you are storing: single (like string, int) or multiple (like List, Array, user defined class).它还取决于您存储的值类型:单个(如 string、int)或多个(如 List、Array、用户定义的类)。 If it's single you can make list of it and then apply sort.如果它是单一的,您可以列出它然后应用排序。
If it's user defined class, then that class must implement IComparable, ClassName: IComparable<ClassName> and override compareTo(ClassName c) as they are more faster and more object oriented than LINQ.如果它是用户定义的类,则该类必须实现 IComparable, ClassName: IComparable<ClassName>并覆盖compareTo(ClassName c) ,因为它们比 LINQ 更快且更面向对象。

The easiest way to get a sorted Dictionary is to use the built in SortedDictionary class:获取排序字典的最简单方法是使用内置的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 will contain the sorted version of sections sortedSections将包含sections的排序版本

Suppose we have a dictionary as假设我们有一个字典

   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) you can use temporary dictionary to store values as : 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);
        }

Required namespace : using System.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);

Order by desc :按描述顺序:

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

Order by Asc :按升序排序:

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

Sort and print:排序和打印:

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

Change descending to acending to change sort order将降序更改为升序以更改排序顺序

A dictionary by definition is an unordered associative structure that contains only values and keys in a hashable way.根据定义,字典是一种无序的关联结构,它仅以可散列的方式包含值和键。 In other words has not a previsible way to orderer a dictionary.换句话说,没有一种可预见的方式来订购字典。

For reference read this article from python language.参考从python语言阅读这篇文章。

Link python data structures链接python数据结构

Best way:最好的办法:

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

The following code snippet sorts a Dictionary by values.以下代码片段按值对字典进行排序。

The code first creates a dictionary and then uses OrderBy method to sort the items.该代码首先创建一个字典,然后使用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);  
    }  
} 

You can sort the Dictionary by value and get the result in dictionary using the code below:您可以按值对字典进行排序,并使用以下代码在字典中获取结果:

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

鉴于您有一本字典,您可以使用下面的一个衬里直接按值对它们进行排序:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM