2009-06-19 38 views
15

Mi diccionario:¿Obtener el último elemento en un diccionario?

Dictionary<double, string> dic = new Dictionary<double, string>(); 

¿Cómo puedo devolver el último elemento en mi diccionario?

+0

define el último elemento: ¿último insertado? último elemento ordenado? –

+0

Estoy asumiendo el último insertado. – RichardOD

+0

elemento insertado por última vez – subprime

Respuesta

41

¿Qué quieres decir con Last? ¿Te refieres al último valor agregado?

La clase Dictionary<TKey,TValue> es una colección desordenada. Agregar y eliminar elementos puede cambiar lo que se considera el primer y el último elemento. Por lo tanto, no hay forma de agregar el último elemento.

Hay una clase de diccionario ordenada disponible en la forma de SortedDictionary<TKey,TValue>. Pero esto se ordenará en función de la comparación de las claves y no del orden en que se agregaron los valores.

EDITAR

Varias personas han mencionado utilizando el siguiente enfoque de estilo de LINQ

var last = dictionary.Values.Last(); 

ser muy cuidadosos acerca del uso de este método. Devolverá el último valor en la colección Valores. Este puede o no ser el último valor agregado al Diccionario. Probablemente sea tan probable que no sea como es.

+1

Upvote para la advertencia al no utilizar el enfoque de estilo LINQ, ya que no devuelve lo que requiere la subprime. – RichardOD

+5

Aunque no hay una versión genérica, hay un OrderedDictionary en el espacio de nombres System.Collection.Specialized que mantiene los elementos en orden de inserción. – LBushkin

+1

@subprime, en ese caso use LastOrDefault en lugar de Last. – JaredPar

0

Si lo que desea es el valor, esto debería funcionar (suponiendo que usted puede utilizar LINQ):

dic.Values.Last() 
+0

También puede usar "dic.Last()" para obtener el par clave/valor completo. Deberían funcionar igual –

0

que puede usar:

dic.Last() 

Pero un diccionario realmente no tiene un último elemento (los pares en el interior no están ordenados de ninguna manera particular). El último elemento siempre será el mismo, pero no es obvio qué elemento podría ser.

0

Con Net 3.5:

string lastItem = dic.Values.Last() 
string lastKey = dic.Keys.Last() 

... pero hay que tener en cuenta que un diccionario no se ordena, por lo que no se puede contar con el hecho de que los valores se mantendrán en el mismo orden.

5

Si está utilizando .NET 3.5, mira:

dic.Keys.Last() 

Si quieres un orden predecible, sin embargo, su uso:

IDictionary<int, string> dic = new SortedDictionary<int, string>(); 
+0

Cada llamada a "Last()" devolverá el mismo resultado, hasta que se realice un insert o "Add()", ¿correcto? ¿En qué punto podría ser posiblemente diferente? – DevinB

+0

Creo que sí, pero dado que es una colección desordenada, la última agregada puede estar en algún lugar en el medio de la colección. No estoy seguro de cómo se implementa internamente o qué devuelve Last(). Alguien con más conocimiento de las partes internas tendría que responder eso. Libera la señal de Skeet. –

18

diccionarios son conjuntos no ordenados - como tal, hay no es concepto de un primer o último elemento. Si busca una clase que se comporta como un diccionario pero mantiene el orden de inserción de los elementos, considere usar OrderedDictionary.

Si está buscando una colección que clasifique los artículos, considere usar SortedDictionary<TKey,TValue>.

Si usted tiene un diccionario existente, y que busca el elemento 'última' dado alguna orden de clasificación, se puede utilizar LINQ para ordenar la colección, algo así como:

myDictionary.Values.OrderBy(x => x.Key).Last(); 

Por cuidado de usar Dictionary.Keys.Last() - mientras la lista de claves se ordena utilizando el valor predeterminado IComparer para el tipo de clave, el valor que obtenga puede no ser el valor esperado.

+1

Hombre que es mucho más breve que mi respuesta +1; – Hardwareguy

3

Considere crear una colección personalizada que contenga una referencia en el método Add de la colección personalizada. Esto establecería un campo privado que contiene la última clave/valor agregado (o ambos) según sus requisitos.

Luego tenga un método Last() que devuelve esto. He aquí una prueba de concepto de clase para mostrar lo que quiero decir (por favor, no golpee la falta de implementación de la interfaz etc- es código de ejemplo):

public class LastDictionary<TKey, TValue> 
{ 
    private Dictionary<TKey, TValue> dict; 

    public LastDictionary() 
    { 
     dict = new Dictionary<TKey, TValue>(); 
    } 

    public void Add(TKey key, TValue value) 
    { 
     LastKey = key; 
     LastValue = value; 
     dict.Add(key, value); 
    } 

    public TKey LastKey 
    { 
     get; private set; 
    } 

    public TValue LastValue 
    { 
     get; private set; 
    } 
} 
+0

Inteligente :-) Puede hacer esto más breve mediante el uso de propiedades automáticas con instaladores privados y captadores públicos. –

+0

@Metro Smurf- muy cierto, gracias. He actualizado el código para incluir estos, creo que hace que el ejemplo sea un poco más fácil de leer. – RichardOD

+0

Una forma mejor de hacerlo sería heredar de Dictionary y luego anular el método Add, donde establecería sus propiedades agregadas, y luego llamar a base.Add (clave, valor). Le ahorraría muchos problemas al delegar manualmente todas las funciones de Dictionary. – sprite

1

Desde el docs:

Para los propósitos de Enumeración, cada elemento en el diccionario se trata como una estructura KeyValuePair que representa un valor y su clave. El orden en que se devuelven los artículos no está definido.

Por lo tanto, no creo que pueda confiar en Dictionary para devolver el último elemento.

Usa otra colección. Tal vez SortedDictionary ...

0

No se debe acceder a un diccionario en orden, por lo tanto, primero, el último no tiene sentido. ¿Desea que el valor sea indexado por la clave más alta?

Dictionary<double, string> dic = new Dictionary<double, string>(); 
double highest = double.MinValue; 
string result = null; 
foreach(double d in dic.keys) 
{ 
    if(d > highest) 
    { 
     result = dic[d]; 
     highest = d; 
    } 
} 
2

En lugar de utilizar:

Dictionary<double, string> 

... usted podría utilizar:

List<KeyValuePair<double, string>> 

Esto le permitiría utilizar el controlador paso a paso para acceder al elemento por orden en lugar de con la tecla .

7

Sé que esta pregunta es demasiado antigua para obtener cualquier voto positivo, pero no me gustó ninguna de las respuestas, así que publicaré la mía con la esperanza de ofrecer otra opción a futuros lectores.

La siguiente no lo hicieron el trabajo para mí en .NET 4.0:

myDictionary.Values.OrderBy(x => x.Key).Last(); 

Sospecho que el problema es que la 'x' representa un valor en el diccionario, y un valor no tiene llave (la el diccionario almacena la clave, los valores del diccionario no). También puedo estar cometiendo un error en mi uso de la técnica.

De cualquier manera, esta solución sería lento para grandes diccionarios, probablemente O (n log n) CS para la gente, porque es clasificar todo el diccionario sólo para conseguir una entrada. Es como reorganizar toda tu colección de DVD solo para encontrar una película específica.


var lastDicVal = dic.Values.Last(); 

está bien establecida como una mala idea. En la práctica, esta solución realmente funciona la mayor parte del tiempo debido a la implementación del diccionario por parte de Microsoft, pero en términos de ingeniería de software no tiene sentido y no se debe confiar en ella. Incluso si funciona todo el tiempo por el resto de la eternidad, representa una práctica de codificación descuidada e insegura.


Mi solución es la siguiente:

var lastValue = dic[dic.Keys.Max()]; 

La función Keys.max() es mucho más rápido que la clasificación O (n) en lugar de O (n log n). Si el rendimiento es lo suficientemente importante como para que incluso O (n) sea demasiado lento, la última clave insertada puede rastrearse en una variable separada utilizada para reemplazar dic.Keys.Max(), que hará toda la búsqueda O (1) además de cualquier sobrecarga que exista en el seguimiento de la última entrada insertada.

0

En lugar de utilizar Linq como sugieren la mayoría de las otras respuestas, puede acceder al último elemento de cualquier objeto de colección a través de la propiedad Count (vea ICollection.Count Property para obtener más información).

Ver el código aquí para ver un ejemplo de cómo utilizar la cuenta para acceder al elemento final en cualquier colección (incluyendo un diccionario):

Dictionary<double, string> dic = new Dictionary<double, string>(); 
var lastElementIndex = dic.Count - 1; 
var lastElement = dic[lastElementIndex]; 

Tenga en cuenta que esto devuelve el último VALOR, no la clave.

Cuestiones relacionadas