Сведения о вопросе

rjevskii

16:03, 1st July, 2020

Теги

c#   .net   sorting   dictionary    

Как вы сортируете словарь по значению?

Просмотров: 1040   Ответов: 18

Мне часто приходится сортировать словарь, состоящий из ключей & значений, по значению. Например, у меня есть hash слов и соответствующих частот, которые я хочу упорядочить по частоте.

Есть SortedList , который хорош для одного значения (скажем, частоты), и я хочу сопоставить его со словом.

SortedDictionary заказы по ключу, а не по значению. Некоторые прибегают к пользовательскому классу, но есть ли более чистый способ?



  Сведения об ответе

#hash

18:03, 1st July, 2020

Использовать 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 .


  Сведения об ответе

baggs

18:03, 1st July, 2020

Воспользуйся:

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


  Сведения об ответе

ASSembler

18:03, 1st July, 2020

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


  Сведения об ответе

LAST

18:03, 1st July, 2020

Оглядываясь вокруг, и используя некоторые функции C# 3.0, мы можем сделать это:

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

Это самый чистый способ, который я видел, и он похож на способ обработки хэшей Ruby.


  Сведения об ответе

dump

18:03, 1st July, 2020

Вы можете отсортировать Словарь по значению и сохранить его обратно в себя (так, чтобы при foreach над ним значения выходили по порядку):

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

Конечно, это может быть неправильно, но это работает.


  Сведения об ответе

prince

18:03, 1st July, 2020

На высоком уровне у вас нет другого выбора, кроме как пройти через весь словарь и посмотреть на каждое значение.

Может быть, это поможет: 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);
    }
);


  Сведения об ответе

$DOLLAR

18:03, 1st July, 2020

Ты все равно никогда не сможешь разобраться в словаре. На самом деле они не заказаны. Гарантии для словаря состоят в том, что коллекции ключей и значений являются итерационными, а значения могут быть получены по индексу или ключу, но нет никакой гарантии какого-либо конкретного порядка. Следовательно, вам нужно будет получить пару значений имени в список.


  Сведения об ответе

pumpa

18:03, 1st July, 2020

Вы не сортируете записи в словаре. Класс словаря в .NET реализован в виде хэш-таблицы - эта структура данных не является сортируемой по определению.

Если вам нужно иметь возможность перебирать свою коллекцию (по ключу) - вам нужно использовать SortedDictionary, который реализован в виде бинарного дерева поиска.

Однако в вашем случае исходная структура не имеет значения, поскольку она сортируется по другому полю. Вам все равно нужно будет отсортировать его по частоте и поместить в новую коллекцию, отсортированную по соответствующему полю (частоте). Так что в этой коллекции частоты-это ключи, а слова-значения. Поскольку многие слова могут иметь одинаковую частоту (и вы собираетесь использовать ее в качестве ключа), вы не можете использовать ни словарь, ни 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);
}


  Сведения об ответе

DO__IT

18:03, 1st July, 2020

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


  Сведения об ответе

ASER

18:03, 1st July, 2020

Или для развлечения вы могли бы использовать некоторые 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));


  Сведения об ответе

$DOLLAR

18:03, 1st July, 2020

Сортировка значений

Здесь показано, как сортировать значения в словаре. Мы видим консольную программу, которую можно скомпилировать в Visual Studio и запустить. Он добавляет ключи в словарь, а затем сортирует их по значениям. Помните, что экземпляры словаря изначально никак не сортируются. Мы используем ключевое слово 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


  Сведения об ответе

lool

18:03, 1st July, 2020

Сортировка списка 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>


  Сведения об ответе

VCe znayu

18:03, 1st July, 2020

Самый простой способ получить сортированный словарь-это использовать встроенный класс 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


  Сведения об ответе

SEEYOU

18:03, 1st July, 2020

Другие ответы хороши, если все, что вы хотите, это иметь список "temporary", отсортированный по значению. Однако если вы хотите иметь словарь, отсортированный по 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 , чтобы получить "inverse" словарь, который отсортирован по Value .

Bijection<K1, K2> является частью Loyc.Collections.dll, но если вы хотите, вы можете просто скопировать исходный код в свой собственный проект.

Примечание: если существует несколько ключей с одинаковым значением, вы не можете использовать Bijection , но вы можете вручную синхронизировать между обычным Dictionary<Key,Value> и BMultiMap<Value,Key> .


  Сведения об ответе

dumai

18:03, 1st July, 2020

Предположим, что у нас есть словарь в виде

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


  Сведения об ответе

dump

18:03, 1st July, 2020

На самом деле в C#, словарях dint есть sort() метода, так как вас больше интересует сортировка по значениям, вы не можете получить значения, пока не предоставите их ключ, короче говоря, вам нужно перебирать их, используя порядок LINQ по,

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, user defined class),
если один, то вы можете составить его список, а затем применить сортировку.
если определяемый пользователем класс, тогда этот класс должен реализовать IComparable,
ClassName: IComparable<ClassName> и переопределить compareTo(ClassName c) , поскольку они более быстры, чем LINQ, и более объектно-ориентированы.


  Сведения об ответе

piter

18:03, 1st July, 2020

Вы можете отсортировать Словарь по значению и получить результат в словаре, используя приведенный ниже код:

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


  Сведения об ответе

прога

18:03, 1st July, 2020

Если у вас есть словарь, вы можете сортировать их непосредственно по значениям, используя ниже одну строку:

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


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться