我们如何按值对字典排序?

时间:2020-03-05 18:37:19  来源:igfitidea点击:

我经常必须按值对由键和值组成的字典进行排序。例如,我有一个单词和各个频率的哈希,我想按频率排序。

有一个SortedList,它适合单个值(例如频率),我想将其映射回单词。

SortedDictionary订单按键而非值排序。有些使用自定义类,但是有没有更干净的方法?

解决方案:

环顾四周,并使用一些C3.0功能,我们可以这样做:

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

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

在较高的层次上,我们别无选择,只能遍历整个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);
    }
);

使用:

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,则只有在使用VisualStudio2008(或者更高版本)的编译器时,才能使用此语法。

var myList = aDictionary.ToList();

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

使用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%等。或者,如果我们将单词频率索引用于" type-ahead",则还可以包含" StartsWith"子句。

无论如何,我们永远都无法对字典进行排序。实际上并没有订购它们。字典的保证是键和值的集合是可迭代的,并且值可以通过索引或者键来检索,但这并不保证任何特定的顺序。因此,我们需要将名称值对放入列表中。

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

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

或者为了娱乐,我们可以使用一些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));
var ordered = dict.OrderBy(x => x.Value);