Сортировка хэш-таблицы по порядку, в котором она была создана - PullRequest
6 голосов
/ 02 ноября 2010

Это похоже на Как сохранить порядок элементов в хеш-таблице , за исключением .NET.

Есть ли в .NET Hashtable или Dictionary, которые позволяют вамполучить доступ к свойству .Index для записи в том порядке, в котором она была добавлена ​​в коллекцию?

Ответы [ 6 ]

5 голосов
/ 02 ноября 2010

A NameValueCollection может извлекать элементы по индексу (но вы не можете запросить индекс определенного ключа или элемента). Таким образом,

var coll = new NameValueCollection();
coll.Add("Z", "1");
coll.Add("A", "2");
Console.WriteLine("{0} = {1}", coll.GetKey(0), coll[0]); // prints "Z = 1"

Однако он ведет себя странно (по сравнению с IDictionary), когда вы добавляете ключ несколько раз:

var coll = new NameValueCollection();
coll.Add("Z", "1");
coll.Add("A", "2");
coll.Add("Z", "3");
Console.WriteLine(coll[0]); // prints "1,3"

Однако поведение хорошо документировано.

Внимание: NameValueCollection не не орудие IDictionary.


В качестве отступления: Dictionary<K,V> не имеет никакого индекса, который вы можете использовать, но если вы только добавляете элементы и никогда не удаляете их, порядок элементов является порядком вставки. Обратите внимание, что это деталь текущей реализации Microsoft: в документации прямо указано, что порядок является случайным, поэтому это поведение может измениться в будущих версиях .NET Framework или Mono.

4 голосов
/ 02 ноября 2010

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

3 голосов
/ 02 ноября 2010

Вы можете использовать отдельный список для хранения элементов в порядке их добавления.Что-то вроде следующего образца:

public class ListedDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
    List<TValue> _list = new List<TValue>();
    Dictionary<TKey, TValue> _dictionary = new Dictionary<TKey,TValue>();

    public IEnumerable<TValue> ListedValues
    {
        get { return _list; }
    }

    public void Add(TKey key, TValue value)
    {
        _dictionary.Add(key, value);
        _list.Add(value);
    }

    public bool ContainsKey(TKey key)
    {
        return _dictionary.ContainsKey(key);
    }

    public ICollection<TKey> Keys { get { return _dictionary.Keys; } }

    public bool Remove(TKey key)
    {
        _list.Remove(_dictionary[key]);
        return _dictionary.Remove(key);
    }

    // further interface methods...
}
3 голосов
/ 02 ноября 2010

Есть ли в .NET Hashtable или Dictionary, который позволяет вам получить доступ к его свойству .Index для записи в том порядке, в котором она была добавлена ​​в коллекцию?Вы можете перечислить все элементы в Hastable или Dictionary, но они не гарантированы в каком-либо порядке (скорее всего, нет)

Вам придется либо использовать другую структуру данных в целом,(например, SortedDictionary или SortedList) или используйте отдельный список для хранения порядка, в котором они были добавлены.Вы бы хотели обернуть упорядоченный список и ваш словарь / хеш-таблицу в другом классе, чтобы синхронизировать их.

2 голосов
/ 08 октября 2012

Посмотрите на класс OrderedDictionary.Вы можете получить к нему доступ не только по ключам, но и по индексу (позиции).

1 голос
/ 28 марта 2012

Альтернативой является создание массива структур, поэтому вместо использования

dictionary.Add{"key1","value1"}

вы создаете структуру с ключом / значением, например:

public struct  myStruct{
    private string _sKey;
    public string sKey{
        get { return _sKey; }
        set { _sKey = value; }
    }
    private string _sValue;
    public string sValue {
        get { return _sValue; }
        set { _sValue = value; }
    }
}

// create list here
List<myStruct> myList = new List<myStruct>();

// create an instance of the structure to add to the list
myStruct item = new myStruct();
item.sKey = "key1";
item.sValue = "value1";

// then add the structure to the list
myList.Add(item);

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

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

...