2012-01-06 7 views
13

Hay un método o técnica que le permite insertar un elemento en Dictionary<TKey, TValue> garantizando que el artículo está en el primer índice de KeyCollection de ese diccionario.¿Cómo insertar un elemento en el primer índice en el diccionario?

Por ejemplo:

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

// `dic` is something like: 

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

necesito algo como:

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

Salida:

key = value 
foo = baa 
a = b 

Cualquier ayuda es muy apreciada. ¡Gracias por adelantado!

+2

¿Cuál es su requisito de hacer uso de un diccionario? El orden de los elementos en una colección de diccionarios está destinado a ser flexible (puede volver a ordenarlos, etc.), el índice está oculto de su uso. Es posible que desee utilizar un tipo diferente de colección que será más apropiado según sus necesidades. –

Respuesta

20

Al no usar un diccionario.

Dictionary<TKey, TValue> se implementa como una tabla hash.La posición de las claves internas del diccionario depende del código hash, el medio por el que ese código hash se redujo aún más para proporcionar un índice en su estructura interna y el orden de inserción de una manera completamente dependiente de la implementación.

Esta no es la única forma de implementar un diccionario. SortedDictionary<TKey, TValue> utiliza una estructura de árbol internamente y, por lo tanto, siempre mantiene las claves en un orden. En este caso, todavía no podemos insertar algo al principio, sino que insertamos algo y se coloca en el lugar apropiado.

Si ordenar es lo que más te importa, entonces no quieres un purificador en absoluto. En su lugar, desea List<KeyValuePair<TKey, TValue>> o una estructura que ofrezca la funcionalidad de una lista y de un diccionario, que se proporciona en OrderedDictionary. Esto no es genérico, pero puede crear fácilmente un contenedor genérico (no da los beneficios de rendimiento de usar genéricos internamente, pero le da seguridad de tipo en uso).

+0

Entonces, ¿cuál es el propósito del método como 'OrderBy'? (Extensión de Linq). ¿En qué orden la enumeración tendría acceso a las entradas? – Keren

+0

@Keren El propósito es recibir elementos ordenados por un criterio particular y algo que se enumere a través de él accedería a los elementos en ese orden. (Se accederá a la fuente en cualquier orden y el orden se producirá cuando se haya completado). No estoy seguro de cómo esto es relevante. –

+0

Lo que estoy tratando de decir es que el diccionario tiene algún tipo de orden que no depende de la 'Clave'. Por esta razón, esperaría una forma de controlar este orden. Entiendo que no hay. – Keren

2

Dictionary<TKey, TValue> es intrínsecamente desordenado (o más bien, el orden es impredecible y no se debe confiar). Si desea algún tipo de pedido, debe usar un tipo diferente. Es difícil recomendar cualquier tipo particular sin saber más acerca de sus requisitos.

2

No se puede pedir el Dictionary<TKey, TValue>.

En su lugar, puede probar SortedDictionary<TKey, TValue>, pero ese es ordenado por la clave, no por un índice separado.

7

Los diccionarios están desordenados; los elementos están destinados a ser recuperados con una clave, cuyo hash apunta a la ubicación de su valor.

Lo que podría querer es un List <KeyValuePair>, cuyos elementos se pueden insertar en un índice específico.

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); 
3

Esto no es posible con Dictionary<TKey, TValue> ya que presenta valores que es de una manera desordenada cuando enumerado. Hay SortedDictionary<TKey, TValue> que proporciona pedidos, pero lo hace usando un IComparer<TKey> directamente contra el valor de la clave. Aquí quiere que la clave sea String y tenga un pedido basado en int. Eso no es posible con ninguno de estos tipos.

Creo que tendrá que implementar un nuevo tipo con esta semántica muy específica en ellos. Por ejemplo.

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

Nota: este viene con algunas diferencias de rendimiento no triviales más de un tradicional Dictionary<TKey, TValue>. Por ejemplo, Add y Remove son más lentos.

1

esta es mi solución, tal vez no la mejor solución, pero funciona. =)

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

Sé que es una pregunta de tres años. Pero encontró una solución a este problema. Puede ayudar a alguien

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

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

Esto insertará el elemento en el comienzo del diccionario :)

+1

Este es un detalle de implementación, también si el diccionario cambia el tamaño de su matriz interna, no se garantiza que el primer elemento permanecerá como primer elemento. –

+0

@MJK Gracias ... esto ayudó .. – Arnab

Cuestiones relacionadas