Сортировка словаря на месте по ключам - PullRequest
67 голосов
/ 24 апреля 2010

У меня есть словарь в C # как

Dictionary<Person, int>

и я хочу отсортировать этот словарь вместо относительно ключей (поле в классе Person). Как мне это сделать? Любая доступная помощь в Интернете - это списки без конкретного примера сортировки словаря на месте. Любая помощь будет принята с благодарностью!

Ответы [ 7 ]

141 голосов
/ 24 апреля 2010

Вы не можете отсортировать Dictionary<TKey, TValue> - это по сути неупорядочено. (Или, скорее, порядок получения записей зависит от реализации. Вы не должны полагаться на то, что он работает одинаково между версиями, так как упорядочение не является частью его разработанной функциональности.)

Вы можете использовать SortedList<TKey, TValue> или SortedDictionary<TKey, TValue>, оба из которых сортируются по ключу (настраиваемым способом, если вы передаете IEqualityComparer<T> в конструктор) - могут ли они быть вам полезны?

Не обращайте внимания на слово «список» в названии SortedList - это все еще словарь, в котором он сопоставляет ключи со значениями. Он реализован , эффективно и эффективно используя список - поэтому вместо поиска по хеш-коду он выполняет двоичный поиск. SortedDictionary аналогично основан на бинарных поисках, но через дерево вместо списка.

23 голосов
/ 24 апреля 2010

Попробуйте использовать SortedDictionary

10 голосов
/ 01 апреля 2015

Правильный ответ уже указан (просто используйте SortedDictionary).

Однако, если случайно у вас возникнет необходимость сохранить свою коллекцию в качестве словаря, можно получить доступ к ключам словаря упорядоченным способом, например, упорядочив ключи в списке, а затем использовать этот список для словарь. Пример ...

Dictionary<string, int> dupcheck = new Dictionary<string, int>();

... некоторый код, который заполняет "dupcheck", затем ...

if (dupcheck.Count > 0) {
  Console.WriteLine("\ndupcheck (count: {0})\n----", dupcheck.Count);
  var keys_sorted = dupcheck.Keys.ToList();
    keys_sorted.Sort();
  foreach (var k in keys_sorted) {
    Console.WriteLine("{0} = {1}", k, dupcheck[k]);
  }
}

Не забудьте using System.Linq; для этого.

7 голосов
/ 24 апреля 2010

Словари по конструкции не сортируются. Если вам нужна эта возможность в словаре, посмотрите вместо этого на SortedDictionary.

4 голосов
/ 24 апреля 2010

Взгляните на SortedDictionary, есть даже перегрузка конструктора, поэтому вы можете передать свой собственный IComparable для сравнения.

3 голосов
/ 08 октября 2016

Хотя словарь реализован в виде хеш-таблицы, SortedDictionary реализован в виде красно-черного дерева.

Если вы не используете порядок в своем алгоритме и вам нужно только отсортировать данные перед выводом, с использованием SortedDictionary будет иметь негативное влияние на производительность .

Вы можете "отсортировать" словарь так:

Dictionary<string, int> dictionary = new Dictionary<string, int>();
// algorithm
return new SortedDictionary<string, int>(dictionary);
1 голос
/ 02 марта 2018

В связи с этим ответом на высокий уровень поиска я подумал, что решение LINQ OrderBy стоит показать:

class Person
{
    public Person(string firstname, string lastname)
    {
        FirstName = firstname;
        LastName = lastname;
    }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

static void Main(string[] args)
{
    Dictionary<Person, int> People = new Dictionary<Person, int>();

    People.Add(new Person("John", "Doe"), 1);
    People.Add(new Person("Mary", "Poe"), 2);
    People.Add(new Person("Richard", "Roe"), 3);
    People.Add(new Person("Anne", "Roe"), 4);
    People.Add(new Person("Mark", "Moe"), 5);
    People.Add(new Person("Larry", "Loe"), 6);
    People.Add(new Person("Jane", "Doe"), 7);

    foreach (KeyValuePair<Person, int> person in People.OrderBy(i => i.Key.LastName))
    {
        Debug.WriteLine(person.Key.LastName + ", " + person.Key.FirstName + " - Id: " + person.Value.ToString());
    }
}

Выход:

Doe, John - Id: 1
Doe, Jane - Id: 7
Loe, Larry - Id: 6
Moe, Mark - Id: 5
Poe, Mary - Id: 2
Roe, Richard - Id: 3
Roe, Anne - Id: 4

В этом примере имеет смысл также использовать ThenBy для имен:

foreach (KeyValuePair<Person, int> person in People.OrderBy(i => i.Key.LastName).ThenBy(i => i.Key.FirstName))

Тогда вывод:

Doe, Jane - Id: 7
Doe, John - Id: 1
Loe, Larry - Id: 6
Moe, Mark - Id: 5
Poe, Mary - Id: 2
Roe, Anne - Id: 4
Roe, Richard - Id: 3

LINQ также имеет OrderByDescending и ThenByDescending для тех, кому это нужно.

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