Есть ли способ отслеживать порядок элементов в словаре? - PullRequest
5 голосов
/ 03 марта 2010

У меня есть Dictionary<Guid, ElementViewModel>. (ElementViewModel - это наш собственный сложный тип.) Я добавляю элементы в словарь со стандартным запасом items.Add(Guid.NewGuid, new ElementViewModel() { /*setters go here*/ });,

На более позднем этапе я удаляю некоторые или все эти элементы.

Упрощенный вид моей ElementViewModel таков:

class ElementViewModel
{
    Guid Id { get; set; }
    string Name { get; set; }
    int SequenceNo { get; set; }
}

Может быть важно отметить, что SequenceNos сжимаются в коллекции после добавления, в случае, если имели место другие операции, такие как перемещение и копирование. {1, 5, 6} -> {1, 2, 3}

Упрощенный вид моей операции удаления:

public void RemoveElementViewModel(IEnumerable<ElementViewModel> elementsToDelete)
{
    foreach (var elementViewModel in elementsToDelete)
        items.Remove(elementViewModel.Id);

    CompactSequenceNumbers();
}

Я проиллюстрирую проблему на примере:

Я добавляю 3 словаря в словарь:

var newGuid = Guid.NewGuid();
items.Add(newGuid, new MineLayoutElementViewModel { Id = newGuid, SequenceNo = 1, Name = "Element 1" });
newGuid = Guid.NewGuid();
items.Add(newGuid, new MineLayoutElementViewModel { Id = newGuid, SequenceNo = 2, Name = "Element 2" });
newGuid = Guid.NewGuid();
items.Add(newGuid, new MineLayoutElementViewModel { Id = newGuid, SequenceNo = 3, Name = "Element 3" });

Удаляю 2 пункта

RemoveElementViewModel(new List<ElementViewModel> { item2, item3 }); //imagine I had them cached somewhere.

Теперь я хочу добавить еще 2 элемента:

newGuid = Guid.NewGuid();
items.Add(newGuid, new MineLayoutElementViewModel { Id = newGuid, SequenceNo = 2, Name = "Element 2, Part 2" });
newGuid = Guid.NewGuid();
items.Add(newGuid, new MineLayoutElementViewModel { Id = newGuid, SequenceNo = 3, Name = "Element 3, Part 2" });

При оценке словаря на данный момент я ожидал, что порядок элементов будет «Элемент 1», «Элемент 2, часть 2», «Элемент 3, часть 2»

но на самом деле это в следующем порядке: «Элемент 1», «Элемент 3, часть 2», «Элемент 2, часть 2»


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

Ответы [ 3 ]

14 голосов
/ 03 марта 2010

.Net Словари не упорядочены по конструкции.

Вы должны использовать вместо KeyedCollection<TKey, TValue>; он сохранит порядок добавления элементов в коллекцию, а также будет использовать хэш-таблицу для быстрого поиска.

Например:

class ElementViewModelCollection : KeyedCollection<Guid, ElementViewModel> {
    protected override Guid GetKeyForItem(ElementViewModel item) { return item.Id; }
}

items.Add(new MineLayoutElementViewModel { Id = Guid.NewGuid(), SequenceNo = 3, Name = "Element 3" });

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

3 голосов
/ 04 марта 2010

Любая причина, по которой вы не используете System.Collections.Generic.SortedDictionary, похоже на то, что вы ищете

0 голосов
/ 09 марта 2010

К сожалению, SortedDictionary недостаточно быстр для огромного количества данных, которые мы должны хранить в нем, а KeyedCollection не справляется с целью сжатия свойства SequenceNo элементов вручную.

Строго говоря, мыЯ должен переписать способ, которым происходит секвенирование, потому что мое решение не самое красивое:

Каждый раз, когда элемент удаляется, обновляйте словарь и повторно добавляйте не удаленные элементы в новый словарь, чтобы сохранить последовательность по умолчанию,-> отвратительная практика, я признаю.Запланируйте изменение, как только у меня будет меньше давления.

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