Как вы сортируете словарь по значению?
Мне часто приходится сортировать словарь, состоящий из ключей и значений, по значению. Например, у меня есть хэш слов и соответствующих частот, которые я хочу упорядочить по частоте.
E сть SortedList
что хорошо для одного значения (скажем, частоты), что я хочу отобразить его обратно на слово.
SortedDictionary заказывает по ключу, а не по значению. Некоторые прибегают к пользовательскому классу, но есть ли более чистый способ?
23 ответа
Использование:
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% и т. Д. Или, если вы используете свой индекс частоты слов для type-ahead
Вы также можете включить StartsWith
пункт также.
Вы можете отсортировать словарь по значению и сохранить его обратно в себе (чтобы при нахождении над ним значения располагались по порядку):
dict = dict.OrderBy(x => x.Value).ToDictionary(x => x.Key, x => x.Value);
Конечно, это может быть не правильно, но это работает.
Оглядываясь вокруг и используя некоторые функции C# 3.0, мы можем сделать это:
foreach (KeyValuePair<string,int> item in keywordCounts.OrderBy(key=> key.Value))
{
// do something with item.Key and item.Value
}
Это самый чистый способ, который я видел, и он похож на способ обработки хэшей в Ruby.
На высоком уровне, у вас нет другого выбора, кроме как пройти весь словарь и посмотреть на каждое значение.
Может быть, это поможет: 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);
}
);
Вы никогда не сможете отсортировать словарь в любом случае. Они на самом деле не заказаны. Гарантии для словаря состоят в том, что наборы ключей и значений являются итеративными, а значения могут быть получены по индексу или ключу, но здесь нет гарантии какого-либо конкретного порядка. Следовательно, вам нужно получить пару имя-значение в список.
Вы не сортируете записи в Словаре. Класс словаря в.NET реализован как хеш-таблица - эта структура данных не сортируется по определению.
Если вам нужно иметь возможность перебирать свою коллекцию (по ключу) - вам нужно использовать SortedDictionary, который реализован в виде дерева двоичного поиска.
В вашем случае, однако, структура источника не имеет значения, потому что она сортируется по другому полю. Вам все равно нужно отсортировать его по частоте и поместить в новую коллекцию, отсортированную по соответствующему полю (частоте). Таким образом, в этой коллекции частоты являются ключами, а слова - значениями. Поскольку многие слова могут иметь одинаковую частоту (и вы собираетесь использовать его в качестве ключа), вы не можете использовать ни Dictionary, ни SortedDictionary (для них требуются уникальные ключи). Это оставляет вас с SortedList.
Я не понимаю, почему вы настаиваете на сохранении ссылки на оригинальный элемент в вашем основном / первом словаре.
Если объекты в вашей коллекции имеют более сложную структуру (больше полей) и вам необходимо иметь возможность эффективно обращаться к ним / сортировать их, используя несколько различных полей в качестве ключей - вам, вероятно, понадобится настраиваемая структура данных, которая будет состоять из основного хранилища, которое поддерживает вставку и удаление O(1) (LinkedList) и несколько структур индексирования - Dictionaries/SortedDictionaries/SortedLists. Эти индексы будут использовать одно из полей вашего сложного класса в качестве ключа и указатель / ссылку на LinkedListNode в LinkedList в качестве значения.
Вам нужно было бы координировать вставки и удаления, чтобы синхронизировать ваши индексы с основной коллекцией (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);
}
Dictionary<string, string> dic= new Dictionary<string, string>();
var ordered = dic.OrderBy(x => x.Value);
return ordered.ToDictionary(t => t.Key, t => t.Value);
Или для удовольствия вы можете использовать некоторые расширения 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>
Сортировать значения
Это показывает, как сортировать значения в словаре. Мы видим консольную программу, которую вы можете скомпилировать в Visual Studio и запустить. Он добавляет ключи в словарь, а затем сортирует их по их значениям. Помните, что экземпляры словаря изначально никак не сортируются. Мы используем ключевое слово LINQ orderby в запросе.
OrderBy Clause Программа, которая сортирует словарь [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
Самый простой способ получить отсортированный словарь - использовать встроенный 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
Другие ответы хороши, если все, что вам нужно, это иметь "временный" список, отсортированный по значению. Однако, если вы хотите, чтобы словарь был отсортирован по 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>
,
На самом деле в C# словари dint имеют методы sort(), так как вас больше интересует сортировка по значениям, вы не можете получать значения до тех пор, пока не предоставите их ключ, короче говоря, вам нужно перебирать их, используя LINQ Order By,
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;
Это также зависит от того, какие ценности вы храните,
это один (например, string, int) или несколько (например, List, Array, пользовательский класс),
если вы одиноки, вы можете составить список, а затем применить сортировку.
если пользовательский класс, то этот класс должен реализовывать IComparable,ClassName: IComparable<ClassName>
и переопределить compareTo(ClassName c)
так как они быстрее, чем LINQ, и более объектно-ориентированы.
Предположим, у нас есть словарь
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);
}
Требуемое пространство имен: 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.
}
Следующий фрагмент кода сортирует словарь по значениям.
Код сначала создает словарь, а затем использует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);
}
}
Сортировка и печать:
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);
}
Измените нисходящий на восходящий, чтобы изменить порядок сортировки
Словарь по определению представляет собой неупорядоченную ассоциативную структуру, которая содержит только значения и ключи в хешируемом виде. Другими словами, не имеет предвидимого способа заказать словарь.
Для справки прочитайте эту статью на языке python.
Связать структуры данных Python
Лучший способ:
var list = dict.Values.OrderByDescending(x => x).ToList();
var sortedData = dict.OrderBy(x => list.IndexOf(x.Value));
Вы можете отсортировать словарь по значению и получить результат в словаре, используя код ниже:
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);