Мне часто приходится сортировать словарь, состоящий из ключей и значений, по значению. Например, у меня есть хэш слов и соответствующих частот, которые я хочу упорядочить по частоте.
Существует SortedList
, который подходит для одного значения (скажем, частоты), которое я хочу сопоставить со словом.
SortedDictionary упорядочивает по ключу, а не по значению. Некоторые прибегают к custom class, но есть ли более чистый способ?
Используйте:
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 или выше, вы можете упростить этот синтаксис до лямбда-синтаксиса - он эквивалентен, но короче. Если вы используете .NET 2.0, вы можете использовать этот синтаксис, только если вы используете компилятор из Visual Studio 2008 (или выше).
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 10%, и т.д. Или если Вы используете свой индекс частотности слова для 'типа вперед', Вы могли бы также включать пункт 'StartsWith' также.
Оглядевшись вокруг и используя некоторые возможности C# 3.0, мы можем это сделать:
foreach (KeyValuePair<string,int> item in keywordCounts.OrderBy(key=> key.Value))
{
// do something with item.Key and item.Value
}
Это самый чистый способ, который я видел, и он похож на способ Ruby для работы с хэшами.
Вы можете сортировать Словарь стоимостью и спасти ее назад к себе (так, чтобы, когда Вы foreach по ней ценности выходите в заказе):
dict = dict.OrderBy(x => x.Value).ToDictionary(x => x.Key, x => x.Value);
Несомненно, это может не быть правильно, но это работает.
На высоком уровне у вас нет другого выбора, кроме как пройтись по всему Словарю и посмотреть на каждое значение.
Возможно, это поможет: 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);
}
);
You' d никогда не быть в состоянии сортировать словарь так или иначе. Им на самом деле не заказывают. Гарантии словаря - то, что ключ и оценивает коллекции, повторяемы, и ценности могут быть восстановлены индексом или ключом, но нет никакой гарантии никакого конкретного заказа. Следовательно Вы должны были бы получить пару стоимости имени в список.
Вы не сортируете записи в Словаре. Класс словаря в.NET осуществлен как hashtable - эта структура данных не поддающаяся сортировке по определению.
Если Вам необходимо повторить по своей коллекции (ключом) - Вы должны использовать SortedDictionary, который осуществлен как Дерево Двоичного поиска.
В Вашем случае однако исходная структура не важна, потому что это сортировано различной областью. Вы должны были бы все еще сортировать его частотой и поместить его в новую коллекцию, сортированную соответствующей областью (частота). Таким образом в этой коллекции частоты - ключи, и слова - ценности. Так как у многих слов может быть та же частота (и Вы собираетесь использовать ее в качестве ключа), Вы не можете использовать ни Словарь, ни SortedDictionary (они требуют уникальных ключей). Это оставляет Вас с SortedList.
Я don' t понимают, почему Вы настаиваете на том, чтобы поддерживать связь с оригинальным пунктом в Вашем главном/первом словаре.
Если бы у объектов в Вашей коллекции была более сложная структура (больше областей), и Вы должны были быть в состоянии эффективно получить доступ/сортировать к ним использующий несколько различных областей в качестве ключей то - Вам, вероятно, была бы нужна таможенная структура данных, которая состояла бы из основного запоминающего устройства, которое поддерживает O (1) вставка и удаление (LinkedList) и несколько структур индексации - Dictionaries/SortedDictionaries/SortedLists. Эти индексы использовали бы одну из областей от Вашего сложного класса как ключ и указатель/ссылка на LinkedListNode< YourClass> в LinkedList как стоимость.
Вы должны были бы скоординировать вставки и удаления, чтобы держать Ваши индексы в синхронизации с главной коллекцией (LinkedList), и удаления будут довольно дорогим I' d думают. Это подобно тому, как индексы базы данных работают - они фантастические для поисков, но они становятся бременем, когда Вы должны выполнить много insetions и удаления.
Все вышеупомянутое только оправдано, если Вы собираетесь сделать некоторый поиск тяжелая обработка. Если Вы только должны произвести их когда-то сортированный частотой тогда, Вы могли бы просто создать список (анонимных) кортежей:
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);
}
Ценности вида
Это шоу, как сортировать ценности в Словаре. Мы видим программу пульта, которую Вы можете собрать в Визуальной Студии и пробеге. Это добавляет ключи к Словарю и затем сортирует их их ценностями. Помните, что случаи Словаря первоначально не сортированы ни в каком случае. Мы используем 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
Или для забавы Вы могли использовать некоторое дополнительное совершенство 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));
Сортировка 'SortedDictionary' перечисляет, чтобы связать в контроль 'ListView', используя VB.NET:
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>
Самый легкий способ получить сортированный Словарь состоит в том, чтобы использовать построенный в классе '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' будет содержать сортированную версию 'разделов'
Другие ответы хороши, если у всего, что Вы хотите, должен быть " temporary" список сортирован Стоимостью. Однако, если Вы хотите сортировать словарь 'Ключом', что automatically synchronizes с другим словарем, который сортирован 'Стоимостью', Вы могли использовать ['Bijection< K1, K2>'; класс] (http://ecsharp.net/doc/code/classLoyc_1_1Collections_1_1Bijection.html).
'Bijection< K1, K2>'; позволяет Вам инициализировать коллекцию с двумя существующими словарями, поэтому если Вы хотите, чтобы один из них был не сортирован, и Вы хотите, чтобы другой был сортирован, Вы могли создать свое взаимно однозначное соответствие с кодексом как
var dict = new Bijection<Key, Value>(new Dictionary<Key,Value>(),
new SortedDictionary<Value,Key>());
Вы можете использовать 'dict' как любой нормальный словарь (это осуществляет 'IDictionary< K, V>';), и затем звонят 'dict. Инверсия', чтобы получить " inverse" словарь, который сортирован 'Стоимостью'.
'Bijection< K1, K2>'; часть [Loyc. Collections.dll] (http://core.loyc.net/), но если Вы хотите, Вы могли бы просто скопировать [исходный код] (https://github.com/qwertie/Loyc/blob/master/Core/Loyc. Collections/Other/Bijection.cs) в Ваш собственный проект.
Отметьте : В случае, если есть несколько ключей с той же стоимостью, Вы can' t используют 'Взаимно однозначное соответствие', но Вы могли вручную синхронизировать между обычным 'Dictionary< Ключ, Value>'; и ['BMultiMap< Стоимость, Key>';] (http://loyc.net/doc/code/classLoyc_1_1Collections_1_1BMultiMap_3_01K_00_01V_01_4.html).
Предположим, что у нас есть словарь как
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);
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);
}
На самом деле в C#, у вмятины Словарей есть вид () методы, поскольку Вы больше интересуетесь видом ценностями, Вы наклоняетесь, получают ценности, пока Вы не обеспечиваете их ключевой, короче говоря, Вы должны повторить через них, использование LINQ' s Заказ,
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;
также зависят от того, какие ценности Вы храните,
действительно ли это единственное (как последовательность, интервал) или несколько (как Список, Множество, пользователь определил класс),
если единственный Вы можете составить список его, тогда применяют вид.
если пользователь определил класс,
тогда тот класс должен осуществить IComparable,
'ClassName: IComparable< ClassName>'; и отвергните 'compareTo (ClassName c)'
поскольку они больше быстрее, чем LINQ и более объектно-ориентированные.
Учитывая Вас имеют словарь, Вы можете сортировать их непосредственно на использовании ценностей ниже одного лайнера:
var x = (from c in dict orderby c.Value.Order ascending select c).ToDictionary(c => c.Key, c=>c.Value);
Вы можете сортировать Словарь стоимостью и получить результат в словаре, используя кодекс ниже:
Dictionary <<string, string>> ShareUserNewCopy =
ShareUserCopy.OrderBy(x => x.Value).ToDictionary(pair => pair.Key,
pair => pair.Value);