Получить последний элемент в словаре? - PullRequest
18 голосов
/ 19 июня 2009

Мой словарь:

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

Как я могу вернуть последний элемент в моем словаре?

Ответы [ 12 ]

48 голосов
/ 19 июня 2009

Что вы подразумеваете под Last? Вы имеете в виду последнюю добавленную стоимость?

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

Существует упорядоченный словарный класс, доступный в форме SortedDictionary<TKey,TValue>. Но это будет упорядочено на основе сравнения ключей, а не в порядке добавления значений.

РЕДАКТИРОВАТЬ

Несколько человек упоминали, что использовали следующий подход в стиле LINQ

var last = dictionary.Values.Last();

Будьте очень осторожны с использованием этого метода. Он вернет последнее значение в коллекции значений. Это может быть или не быть последним значением, которое вы добавили в словарь. Скорее всего, это будет не так, как должно быть.

20 голосов
/ 19 июня 2009

Словари являются неупорядоченными коллекциями - как таковые, нет понятия первого или последнего элемента. Если вы ищете класс, который ведет себя как словарь, но поддерживает порядок вставки элементов, рассмотрите возможность использования OrderedDictionary.

Если вы ищете коллекцию, которая сортирует предметы, рассмотрите возможность использования SortedDictionary<TKey,TValue>.

Если у вас уже есть словарь, и вы ищете последний элемент с заданным порядком сортировки, вы можете использовать linq для сортировки коллекции, например:

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

Опасаясь использования Dictionary.Keys.Last() - хотя список ключей сортируется с использованием значения по умолчанию IComparer для типа ключа, полученное вами значение может не соответствовать ожидаемому.

7 голосов
/ 20 сентября 2011

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

Следующие не работают у меня в .NET 4.0:

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

Я подозреваю, что проблема в том, что «x» представляет значение в словаре, а значение не имеет ключа (словарь хранит ключ, значения словаря - нет). Возможно, я тоже ошибаюсь в использовании этой техники.

В любом случае, это решение будет медленным для больших словарей, вероятно O (n log n) для пользователей CS, потому что это сортировка всего словаря только для получения одной записи , Это все равно, что переставить всю коллекцию DVD, чтобы найти один конкретный фильм.


var lastDicVal = dic.Values.Last();

хорошо зарекомендовал себя как плохая идея. На практике это решение действительно работает большую часть времени из-за реализации словаря Microsoft, но в терминах разработки программного обеспечения это бессмысленно и на него нельзя полагаться. Даже если он работает каждый раз до конца вечности, он представляет собой небрежную, небезопасную практику кодирования.


Мое решение заключается в следующем:

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

Функция Keys.max () намного быстрее, чем сортировка O (n) вместо O (n log n) . Если производительность настолько важна, что даже O (n) слишком медленный, последний вставленный ключ может отслеживаться в отдельной переменной, используемой для замены dic.Keys.Max () , которая выполнит весь поиск O (1) плюс любые накладные расходы на отслеживание последней вставленной записи.

5 голосов
/ 19 июня 2009

Если вы используете .NET 3.5, посмотрите на:

 dic.Keys.Last()

Если вы хотите предсказуемый порядок, используйте:

IDictionary<int, string> dic = new SortedDictionary<int, string>();
3 голосов
/ 24 февраля 2011

Вместо использования:

Dictionary<double, string>

... вы можете использовать:

List<KeyValuePair<double, string>>

Это позволит вам использовать индексатор для доступа к элементу по порядку, а не по ключу.

3 голосов
/ 19 июня 2009

Рассмотрите возможность создания пользовательской коллекции, содержащей ссылку в методе Add пользовательской коллекции. Это установит личное поле, содержащее последний добавленный ключ / значение (или оба) в зависимости от ваших требований.

Тогда есть метод Last(), который возвращает это. Вот подтверждение класса понятия, чтобы показать, что я имею в виду (пожалуйста, не выбивайте недостаток реализации интерфейса и т. Д. - это пример кода):

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;
    }
}
1 голос
/ 19 июня 2009

Из документов :

Для целей перечисления каждый элемент в словаре трактуется как KeyValuePair структура, представляющая значение и его ключ. Порядок, в котором предметы возвращены не определено .

Итак, я не думаю, что вы можете положиться на Dictionary, чтобы вернуть последний элемент.

Использовать другую коллекцию. Может быть SortedDictionary ...

0 голосов
/ 02 марта 2016

Вместо использования Linq, как предлагают другие ответы, вы можете просто получить доступ к последнему элементу любого объекта Collection через свойство Count (для получения дополнительной информации см. Свойство ICollection.Count ).

См. Здесь код для примера того, как использовать счетчик для доступа к конечному элементу в любой коллекции (включая словарь):

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

Имейте в виду, что это возвращает последнее ЗНАЧЕНИЕ , а не ключ.

0 голосов
/ 19 июня 2009

Словарь не предназначен для доступа по порядку, поэтому, во-первых, последний не имеет значения. Вы хотите, чтобы значение индексировалось по верхнему ключу?

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;
   }
}
0 голосов
/ 19 июня 2009

С .Net 3.5:

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

... но помните, что словарь не упорядочен, поэтому вы не можете рассчитывать на тот факт, что значения останутся в том же порядке.

...