如何在字典中的第一个索引中插入元素?

时间:2012-01-06 16:33:13

标签: c# .net dictionary

是否有允许您将元素插入的方法或技术 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 个答案:

答案 0 :(得分:22)

不使用字典。

Dictionary<TKey, TValue>实现为哈希表。字典内部的键的位置取决于散列码,散列码进一步减少以提供其内部结构的索引的方式,以及完全依赖于实现的方式的插入顺序。

这不是实现字典的唯一方法。 SortedDictionary<TKey, TValue>在内部使用树结构,因此始终保持按键顺序。在这种情况下,我们仍然无法在开头插入一些内容,而是插入一些内容并将其放在适当的位置。

如果订购是您最关心的,那么您根本不想要一个puringictionary。相反,你想要一个List<KeyValuePair<TKey, TValue>>,或者你想要一个既提供列表功能又提供字典功能的结构,由OrderedDictionary提供。这不是通用的,但您可以轻松地围绕它创建一个通用的包装器(不会提供内部使用泛型的性能优势,但确实使用了类型安全性。)

答案 1 :(得分:8)

字典无序;元素意味着使用键检索,其哈希值指向其值的位置。

您可能需要的是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);

答案 2 :(得分:7)

我知道这是一个三年前的问题。 但找到了此问题的解决方法 。它可能会帮助某人

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

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

这会将元素插入字典的开头:)

答案 3 :(得分:3)

这对于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>相比,这确实存在一些非平凡的性能差异。例如,AddRemove较慢。

答案 4 :(得分:2)

Dictionary<TKey, TValue>本质上是无序的(或者更确切地说,排序是不可预测的,不应该依赖它)。如果您想要某种排序,则需要使用其他类型。如果不了解您的要求,很难推荐任何特定类型。

答案 5 :(得分:2)

Dictionary<TKey,TValue>类没有按顺序保存项目,因此没有“第一”项。

有一个SortedDictionary<Tkey,TValue>(.NET 4.0+),它按键排序,但同样,这是一个非常模糊的“第一”概念。

答案 6 :(得分:2)

无法订购Dictionary<TKey, TValue>

你可以试试SortedDictionary<TKey, TValue>,但是那个是按键排序的,而不是单独的索引。

答案 7 :(得分:2)

这是我的解决方案,也许不是最好的解决方案,但它有效。 =)

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;
}

答案 8 :(得分:1)

Dictionary是一个无序的集合。您可以尝试OrderedDictionary - http://msdn.microsoft.com/en-us/library/system.collections.specialized.ordereddictionary.aspx - 其中包含Insert()方法,这就是您所追求的方法。