Как вставить элемент в первый индекс в словаре? - PullRequest
15 голосов
/ 06 января 2012

Существует ли метод или метод, позволяющий вставить элемент в Dictionary<TKey, TValue> гарантирует, что элемент находится в первом индексе KeyCollection этого словаря.

Например:

Dictionary<String, String> dic = foo.GetOutput(); 

// `dic` is something like:

// {"foo", "baa"},
// {"a", "b"}

Мне нужно что-то вроде:

dic.Add("key", "value", 0);
// where `0` is the index that `key` to be inserted.

foreach(KeyValuePair<String, String> key in dic) 
{
     Console.WriteLine("{0} = {1}", key.Key, key.Value);
}

Выход:

key = value
foo = baa
a = b

Ответы [ 9 ]

23 голосов
/ 06 января 2012

Не используя словарь.

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

Это не единственный способ реализовать словарь.SortedDictionary<TKey, TValue> использует внутреннюю древовидную структуру и поэтому всегда хранит ключи в порядке.В этом случае мы все еще не можем вставить что-то в начале, мы вставляем что-то, и оно помещается в нужное место.

Если упорядочение - это то, что вас больше всего волнует, то вам не нужен чистый приговорсовсем.Скорее вы хотите либо List<KeyValuePair<TKey, TValue>>, либо структуру, которая предлагает как функциональность списка, так и словаря, который предоставляется OrderedDictionary.Это не универсальный, но вы можете легко создать универсальную обертку вокруг него (не дает преимуществ в производительности при внутреннем использовании универсальных шаблонов, но обеспечивает безопасность при использовании).

8 голосов
/ 06 января 2012

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

Вам может потребоваться List <KeyValuePair>, элементы которого могут быть вставлены в определенный индекс.

List<KeyValuePair<string, string>> list = dic.ToList();
list.Insert(0, new KeyValuePair<string, string>("a", "b"));

foreach(KeyValuePair<string, string> pair in list)
    Console.WriteLine("{0} = {1}", pair.Key, pair.Value);
7 голосов
/ 30 декабря 2015

Я знаю, что это вопрос трех лет. Но нашел решение этой проблемы . Это может помочь кому-то

Dictionary<String, String> dic = foo.GetOutput();

dic = (new Dictionary<string, string> {{"key","value"}}).Concat(dic).ToDictionary(k => k.Key, v => v.Value);

Это вставит элемент в начало словаря:)

3 голосов
/ 06 января 2012

Это невозможно с Dictionary<TKey, TValue>, поскольку при перечислении он представляет неупорядоченные значения.Существует SortedDictionary<TKey, TValue>, который обеспечивает порядок, но он делает это, используя IComparer<TKey> непосредственно против значения ключа.Здесь вы хотите, чтобы ключ был String и имел порядок на основе int.Это невозможно с любым из этих типов.

Я думаю, вам нужно реализовать новый тип с этими очень специфическими семантиками в них.Например.

class OrderedMap<TKey, TValue> {
  private readonly Dictionary<TKey, TValue> _map = new Dictionary<TKey, TValue>();
  private readonly List<TKey> _list = new List<TKey>();

  public void Add(TKey key, TValue value) {
    if (!_map.ContainsKey(key)) {
      _list.Add(key);
    }
    _map[key] = value;
  }

  public void Add(TKey key, TValue value, int index) {
    if (_map.ContainsKey(key)) {
      _list.Remove(key);
    }
    _map[key] = value;
    _list.Insert(index, key);
  }

  public TValue GetValue(TKey key) {
    return _map[key];
  }

  public IEnumerabe<KeyValuePair<TKey, TValue>> GetItems() {
    foreach (var key in _list) { 
      var value = _map[key];
      yield return new KeyValuePair<TKey, TValue>(key, value);
    }
  }
}

Обратите внимание, что это имеет некоторые нетривиальные различия в производительности по сравнению с традиционным Dictionary<TKey, TValue>.Например, Add и Remove медленнее.

2 голосов
/ 08 января 2014

это моё решение, возможно, не лучшее решение, но оно работает.=)

public static ComboBox FillDropDownList(Dictionary<String, String> dictionary, ComboBox dropDown, String selecione)
{
    var d = new SortedDictionary<String, String>();

    d.Add("0", selecione);

    foreach (KeyValuePair<string, string> pair in dictionary)
    {
        d.Add(pair.Key, pair.Value);
    }

    dropDown.DataSource = new BindingSource(d, null);
    dropDown.DisplayMember = "Value";
    dropDown.ValueMember = "Key";

    dropDown.SelectedIndex = 0;

    return dropDown;
}
2 голосов
/ 06 января 2012

Dictionary<TKey, TValue> нельзя заказать.

Вместо этого вы можете попробовать SortedDictionary<TKey, TValue>, но этот порядок назначается ключом, а не отдельным индексом.

2 голосов
/ 06 января 2012

Класс Dictionary<TKey,TValue> не содержит элементы упорядоченным образом, поэтому «первый» элемент отсутствует.

Существует SortedDictionary<Tkey,TValue>(.NET 4.0+), который сортирует по ключу, но опять же, это очень смутное представление о «первом».

2 голосов
/ 06 января 2012

Dictionary<TKey, TValue> изначально неупорядочен (или, скорее, порядок непредсказуем и на него нельзя полагаться). Если вы хотите какой-то порядок, вам нужно использовать другой тип. Трудно рекомендовать какой-либо конкретный тип, не зная больше о ваших требованиях.

1 голос
/ 06 января 2012

A Dictionary - неупорядоченная коллекция.Вы можете попробовать OrderedDictionary - http://msdn.microsoft.com/en-us/library/system.collections.specialized.ordereddictionary.aspx - у которого есть метод Insert(), который вам нужен.

...