Как отсортировать словарь, связанный с элементами из коллекции списков C#

У меня есть список (myList) с именами таблиц, упорядоченных по последовательности. MyObject имеет 2 свойства Table (string) и Sequence (int)

List<MyObject>

Пример:

List<MyObject>[0] = MyObject.Sequence = 0, MyObject.Table = "Cat" 
List<MyObject>[1] = MyObject.Sequence = 1, MyObject.Table = "Dog" 
List<MyObject>[2] = MyObject.Sequence = 2, MyObject.Table = "Bird" 
List<MyObject>[3] = MyObject.Sequence = 3, MyObject.Table = "Fish" 

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

dict[0] = key (ID = 1, Table = "Cat" ), EntityObject = Cat 
dict[1] = key (ID = 2, Table = "Dog"), EntityObject = Dog 
dict[2] = key (ID = 3, Table = "Bird"), EntityObject = Bird 
dict[3] = key (ID = 4, Table = "Fish"), EntityObject = Fish 
dict[4] = key (ID = 5, Table = "Cat" ), EntityObject = Cat 
dict[5] = key (ID = 6, Table = "Dog"), EntityObject = Dog 
dict[6] = key (ID = 7, Table = "Cat" ), EntityObject = Cat 
dict[7] = key (ID = 8, Table = "Dog"), EntityObject = Dog 
dict[8] = key (ID = 9, Table = "Cat" ), EntityObject = Cat 
dict[9] = key (ID = 10, Table = "Fish"), EntityObject = Fish

Итак, я хочу упорядочить свой словарь в соответствии со списком, содержащим последовательность таблиц, и перестроить словарь, чтобы он был таким

dict[0] = key (ID = 1, Table = "Cat"), EntityObject = Cat 
dict[1] = key (ID = 5, Table = "Cat"), EntityObject = Cat 
dict[2] = key (ID = 7, Table = "Cat"), EntityObject = Cat 
dict[3] = key (ID = 9, Table = "Cat"), EntityObject = Cat 
dict[4] = key (ID = 2, Table = "Dog"), EntityObject = Dog 
dict[5] = key (ID = 6, Table = "Dog"), EntityObject = Dog 
dict[6] = key (ID = 8, Table = "Dog"), EntityObject = Dog 
dict[7] = key (ID = 3, Table = "Bird"), EntityObject = Bird 
dict[8] = key (ID = 4, Table = "Fish"), EntityObject = Fish 
dict[9] = key (ID = 10, Table = "Fish"), EntityObject = Fish

Я хочу избежать цикла с помощью foreach, а затем воссоздать новый словарь, а затем скопировать или клонировать его в существующий. Итак, я попробовал этот полет на мгновение, но у меня всегда был один и тот же несортированный список. Возможно, мне не хватает метода Sort или OrderBy, но кто-то может помочь это исправить. Предложения?

Dictionary<MyStruct, EntityObject> dict = this.GetDictionary()
    .ToList()
    .FindAll(x => x.Key.Table == myList.Find(y => y.Table == x.Key.Table).Table)
    .ToDictionary(a => a.Key, b => b.Value);

ПРИМЕЧАНИЕ:

Ребята, я уже знаю, что словарь нельзя отсортировать, но если вы видите мой подход, я воссоздаю новый словарь, пытаясь упорядочить элементы в памяти и назначить его «dict».

---ИЗМЕНИТЬ---

Я недавно сделал эту модификацию, но пока ничего. Помоги пожалуйста.

Dictionary<MyStruct, EntityObject>
        dict = this.GetDictionary()
                .ToList()
                .OrderBy(x => x.Key.Table == myList
                .Find(z => z.Table == x.Key.Table).Table)
                .ToDictionary(x => x.Key, y => y.Value);

person Maximus Decimus    schedule 09.11.2013    source источник
comment
I already know that a dictionary can't be sorted ... I'm recreating a new dictionary trying to order the elements, а теперь вы должны увидеть, в чем ваша проблема. Словарь не содержит порядок, порядок, который вы вставляете в словарь, не влияет на его размещение в памяти. Если вы хотите, чтобы он вел себя так, как вы описываете, вам нужно переключиться на что-то другое, например OrderedDictionary или KeyedCollection как описывает Деннис .   -  person Scott Chamberlain    schedule 10.11.2013


Ответы (2)


Словари предназначены для быстрого поиска значений по ключу. Следовательно, словарь оптимизирует свое внутреннее хранилище для целей поиска, так что, по сути, словари представляют собой неупорядоченные структуры данных. То же самое верно и для других контейнеров, которые используют поиск по хэшу (например, HashSet).

Когда вы добавляете элемент в словарь, он вычисляет хэш-код предоставленного ключа и помещает значение в корзину, соответствующую рассчитанному хэш-коду. Он не добавляет значение в конец коллекции (по сравнению, например, с List<T>). Таким образом, «порядок» или элементы определяются только хэш-кодом ключа.

Если вы хотите сохранить порядок некоторых элементов (точнее, если вы хотите получить доступ к элементам по индексу) и при этом использовать словарь, вам потребуется специальная реализация, например OrderedDictionary или KeyedCollection.

person Dennis    schedule 09.11.2013

Вы не можете сортировать Dictionary<K, V>. Он основан на хеш-таблице. Порядок сортировки зависит от хеш-ключа и используемого алгоритма. Получается непредсказуемый порядок.

Есть SortedDictionary<K, V>, но он отсортирован по ключу. Это не то, что вы хотите.

Чтобы использовать порядковый номер для сортировки, вы должны сохранить их в словаре по имени таблицы.

var tableSequence = new Dictionary<string, int>();
tableSequence.Add("Cat", 0);
tableSequence.Add("Dog", 1);
...

Затем вы можете использовать эту информацию для сортировки объектов сущностей:

Dictionary<MyStruct, EntityObject> dict = this.GetDictionary();
var orderedList = dict
    .OrderBy(x => tableSequence[x.Key.Table])
    .ToList();

Сохранение этой информации обратно в словарь нарушило бы порядок сортировки.


Есть еще System.Collections.Specialized.OrderedDictionary, но он не универсальный. Примечание: он упорядочен, а не отсортирован. Это означает, что элементы сохраняются в том порядке, в котором вы их ввели. Таким образом, в основном вам придется добавлять предварительно отсортированные элементы в цикл один за другим. Затем вы можете получить доступ к элементам либо по индексу, либо по ключу.

person Olivier Jacot-Descombes    schedule 09.11.2013