Estoy usando un Dictionary<string, int>
donde el int
es un recuento de la clave.
Ahora, necesito acceder a la última Clave insertada dentro del Diccionario, pero no sé su nombre. El intento obvio:
int LastCount = mydict[mydict.keys[mydict.keys.Count]];
no funciona porque Dictionary.Keys
no implementa un indexador [].
Me pregunto si hay alguna clase similar? Pensé en usar una pila, pero eso solo almacena una cadena. Ahora podría crear mi propia estructura y luego usar a Stack<MyStruct>
, pero me pregunto si hay otra alternativa, esencialmente un diccionario que implementa un índice [] en las teclas.
c#
.net
dictionary
Michael Stum
fuente
fuente
Respuestas:
Como @Falanwe señala en un comentario, hacer algo como esto es incorrecto :
No debe depender del orden de las teclas en un Diccionario. Si necesita ordenar, debe usar un OrderedDictionary , como se sugiere en esta respuesta . Las otras respuestas en esta página también son interesantes.
fuente
HashTable
System.Collections.ICollection 'no contiene una definición para' ElementAt 'y no se puede encontrar ningún método de extensión' ElementAt 'que acepte un primer argumento de tipo' System.Collections.ICollection 'ElementAtOrDefault
versión para trabajar con la versión sin excepción.Dictionary<TKey,TValue>
documentación , "el orden de las claves en elDictionary<TKey, TValue>.KeyCollection
no está especificado". El orden no está definido, no tiene forma de saber con certeza cuál está en la última posición (mydict.Count -1
)Puedes usar un OrderedDictionary .
fuente
Un diccionario es una tabla hash, por lo que no tiene idea del orden de inserción.
Si desea conocer la última clave insertada, le sugiero extender el Diccionario para incluir un valor LastKeyInserted.
P.ej:
Tendrá problemas, sin embargo, cuando lo utilice
.Remove()
para superar esto, deberá mantener una lista ordenada de las claves insertadas.fuente
¿Por qué no simplemente extiende la clase del diccionario para agregar una última propiedad insertada en la clave? Algo como lo siguiente tal vez?
fuente
Siempre puedes hacer esto:
Pero no lo recomendaría. No hay garantía de que la última clave insertada esté al final de la matriz. El pedido de claves en MSDN no está especificado y está sujeto a cambios. En mi breve prueba, parece estar en orden de inserción, pero sería mejor construir una contabilidad adecuada como una pila, como sugiere (aunque no veo la necesidad de una estructura basada en su otras declaraciones) - o caché de variable única si solo necesita conocer la última clave.
fuente
Creo que puede hacer algo como esto, la sintaxis puede estar equivocada, no he usado C # en un tiempo para obtener el último elemento
o use Max en lugar de Last para obtener el valor máximo, no sé cuál se ajusta mejor a su código.
fuente
Estoy de acuerdo con la segunda parte de la respuesta de Patrick. Incluso si en algunas pruebas parece mantener el orden de inserción, la documentación (y el comportamiento normal de los diccionarios y hashes) declara explícitamente que el orden no está especificado.
Solo está pidiendo problemas dependiendo del orden de las llaves. Agregue su propia contabilidad (como dijo Patrick, solo una variable para la última clave agregada) para estar seguro. Además, no se deje tentar por todos los métodos, como Last y Max en el diccionario, ya que probablemente estén relacionados con el comparador de claves (no estoy seguro de eso).
fuente
En caso de que decida usar un código peligroso que esté sujeto a roturas, esta función de extensión obtendrá una clave de
Dictionary<K,V>
acuerdo con su indexación interna (que para Mono y .NET actualmente parece estar en el mismo orden que usted al enumerar laKeys
propiedad )Es mucho preferible usar Linq:,
dict.Keys.ElementAt(i)
pero esa función repetirá O (N); el siguiente es O (1) pero con una penalización de rendimiento de reflexión.fuente
Una alternativa sería KeyedCollection si la clave está incrustada en el valor.
Simplemente cree una implementación básica en una clase sellada para usar.
Entonces, para reemplazar
Dictionary<string, int>
(que no es un muy buen ejemplo, ya que no hay una clave clara para un int).fuente
La forma en que redactó la pregunta me lleva a creer que el int en el Diccionario contiene la "posición" del elemento en el Diccionario. A juzgar por la afirmación de que las claves no se almacenan en el orden en que se agregaron, si esto es correcto, eso significaría que las claves.Count (o .Count - 1, si está utilizando cero) aún deberían siempre será el número de la última clave ingresada?
Si eso es correcto, ¿hay alguna razón por la que no puedas usar Dictionary <int, string> para que puedas usar mydict [mydict.Keys.Count]?
fuente
No sé si esto funcionaría porque estoy bastante seguro de que las claves no se almacenan en el orden en que se agregan, pero puede convertir KeysCollection en una lista y luego obtener la última clave en la lista ... pero valdría la pena echarle un vistazo.
La única otra cosa que se me ocurre es almacenar las claves en una lista de búsqueda y agregar las claves a la lista antes de agregarlas al diccionario ... aunque no es bastante bueno.
fuente
Para ampliar la publicación de Daniels y sus comentarios con respecto a la clave, ya que la clave está incrustada en el valor de todos modos, puede recurrir a usar a
KeyValuePair<TKey, TValue>
como valor. El razonamiento principal para esto es que, en general, la clave no necesariamente se deriva directamente del valor.Entonces se vería así:
Para usar esto como en el ejemplo anterior, haría:
fuente
Un diccionario puede no ser muy intuitivo para usar el índice como referencia, pero puede tener operaciones similares con una matriz de KeyValuePair :
ex.
KeyValuePair<string, string>[] filters;
fuente
También puede usar SortedList y su contraparte genérica. Estas dos clases y en la respuesta de Andrew Peters mencionan que OrderedDictionary son clases de diccionario en las que se puede acceder a los elementos por índice (posición) y por clave. Cómo utilizar estas clases puede encontrar: Clase SortedList , Clase Genérica SortedList .
fuente
UserVoice de Visual Studio ofrece un enlace a la implementación genérica de OrderedDictionary por dotmore.
Pero si solo necesita obtener pares clave / valor por índice y no necesita obtener valores por claves, puede usar un simple truco. Declare alguna clase genérica (la llamé ListArray) de la siguiente manera:
También puede declararlo con constructores:
Por ejemplo, lee algunos pares clave / valor de un archivo y solo desea almacenarlos en el orden en que fueron leídos para obtenerlos luego por índice:
Como habrás notado, no necesariamente puedes tener solo pares de clave / valor en tu ListArray. Las matrices de elementos pueden ser de cualquier longitud, como en una matriz irregular.
fuente