Вопрос по c#, .net – Получить последний элемент в словаре?

16

Мой словарь:

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

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

последний вставленный элемент subprime
Я предполагаю, что последний вставленный. RichardOD
Забавно, сколько голосов за неправильные ответы! RichardOD
@ LBushkin - вот почему я рекомендую создать класс-оболочку. RichardOD
определить последний элемент: последний вставленный? последний отсортированный элемент? Sasha

Ваш Ответ

12   ответов
1

Отдокументы:

For purposes of enumeration, each item in the dictionary is treated as a KeyValuePair structure representing a value and its key. The order in which the items are returned is undefined.

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

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

7

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

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

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

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

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


var lastDicVal = dic.Values.Last();

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


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

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

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

20

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

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

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

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

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

Человек, который более лаконичен, чем мой ответ +1;
0

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

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

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

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

5

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

 dic.Keys.Last()

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

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

Рассмотрите возможность создания пользовательской коллекции, содержащей ссылку в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;
    }
}
@ Metro Smurf - очень верно, спасибо. Я обновил код, чтобы включить их - я полагаю, что это немного облегчает чтение примера.
@ Sprite - да, лучше использовать наследующий словарь, за исключением того, что Add не является виртуальным, поэтому у вас возникла проблема
Лучший способ сделать это - наследовать от Dictionary & lt; TKey, TValue & gt; а затем просто переопределите метод Add, где вы должны установить добавленные свойства, а затем вызовите base.Add (ключ, значение). Избавит вас от лишних хлопот, делегируя все функции словаря вручную.
Умно :-) Вы можете сделать это более кратким, используя автоматические свойства с частными установщиками и общедоступными получателями.
0

Если вы просто хотите получить значение, это должно сработать (при условии, что вы можете использовать LINQ):

dic.Values.Last()
Вы также можете использовать & quot; dic.Last () & quot; чтобы получить всю пару ключ / значение. Они должны работать одинаково
0

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

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

С .Net 3.5:

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

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

0

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

dic.Last()

Но в словаре действительно нет последнего элемента (пары внутри не упорядочены каким-либо определенным образом). Последний элемент всегда будет одинаковым, но не очевидно, каким элементом он может быть.

2

Вместо того, чтобы использовать:

Dictionary<double, string>

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

List<KeyValuePair<double, string>>

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

46

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

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

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

EDIT

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

var last = dictionary.Values.Last();

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

Upvote за предупреждение о том, что не используется подход стиля LINQ, так как он не возвращает того, что требуется для subprime.
Хотя универсальной версии не существует, в пространстве имен System.Collection.Specialized есть OrderedDictionary, поддерживающий элементы в порядке вставки.
JaredPar спасибо! работает отлично! subprime
@subprime, в этом случае используйте LastOrDefault вместо Last.

Похожие вопросы