提问



我经常需要对字典进行排序,包括键和字典。价值,按价值。例如,我有一个单词的散列和各自的频率,我想按频率排序。


有一个SortedList对单个值(比如频率)有好处,我想将它映射回单词。


SortedDictionary按键排序,而不是值。有些人诉诸自定义课程,但有更清除的方式吗?[42] [43]

最佳参考


使用:


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

其它参考1


使用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子句。

其它参考2


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

其它参考3


环顾四周,并使用一些C#3.0功能,我们可以这样做:


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


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

其它参考4


您可以按值对字典进行排序并将其保存回自身(这样当您对其进行预处理时,值将按顺序排出):


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


当然,它可能不正确,但它确实有效。

其它参考5


在较高的层面上,您没有其他选择可以遍历整个字典并查看每个值。


也许这有助于:
http://bytes.com/forum/thread563638.html
约翰·蒂姆尼复制/粘贴:[44]


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


你永远无法对字典进行排序。它们实际上并没有被排序。字典的保证是密钥和值集合是可迭代的,值可以通过索引或密钥检索,但这里不保证任何因此,您需要将名称值对添加到列表中。

其它参考7


您不对词典中的条目进行排序。 .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


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


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

其它参考10


排序值


这显示了如何对Dictionary中的值进行排序。我们看到一个可以在Visual Studio中编译并运行的控制台程序。它为Dictionary添加键,然后按其值对它们进行排序。请记住,Dictionary实例最初不以任何方式排序。我们在查询语句中使用LINQ orderby关键字。


OrderBy条款
排序字典[[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

其它参考11


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


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


其他答案都很好,如果你想要的是有一个按值排序的临时列表。但是,如果您希望按Key排序的字典自动同步与另一个按Value排序的字典,则可以使用Bijection<K1, K2>类。 [45]


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


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


您可以像任何普通字典一样使用dict(它实现IDictionary<>),然后调用dict.Inverse来获得按Value排序的反向字典。


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


注意:如果有多个键具有相同的值,则不能使用Bijection,但您可以在普通Dictionary<Key,Value>BMultiMap<Value,Key>之间手动同步]]。[48]

其它参考14


假设我们有一本字典


   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


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


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

其它参考16


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


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