Accesarea unei chei de cuvinte cheie Dicționar printr-un index numeric

I'm using a Dictionary where the int is a count of the key.

Acum, trebuie să accesez ultima cheie introdusă în dicționar, dar nu-i cunosc numele. Tentativă evidentă:

int LastCount = mydict[mydict.keys[mydict.keys.Count]];

nu funcționează, deoarece Dictionary.Keys nu implementează un index [].

I just wonder if there is any similar class? I thought about using a Stack, but that only stores a string. I could now create my own struct and then use a Stack, but I wonder if there is another alternative, essentially a Dictionary that implements an []-indexer on the Keys?

0
fr hi bn
Ce se întâmplă dacă plasați această variabilă?
adăugat autor Paul Prewett, sursa

9 răspunsuri

Sunt de acord cu a doua parte a răspunsului lui Patrick. Chiar dacă în unele teste pare să păstreze ordinea inserției, documentația (și comportamentul normal pentru dicționare și hashes) declară explicit că ordonarea este nespecificată.

Doar solicitați probleme în funcție de comanda cheilor. Adăugați-vă propriile contabilități (după cum a spus Patrick, doar o singură variabilă pentru ultima cheie adăugată) pentru a fi sigur. De asemenea, nu fiți ispitiți de toate metodele cum ar fi Last și Max în dicționar, deoarece acestea sunt probabil în legătură cu comparatorul cheie (nu sunt sigur de asta).

0
adăugat

Nu știu dacă acest lucru ar funcționa deoarece sunt destul de sigur că cheile nu sunt stocate în ordinea în care sunt adăugate, dar ați putea arunca KeysCollection într-o listă și apoi să obțineți ultima cheie din listă ... dar ar merita să aruncați o privire.

Singurul lucru la care mă pot gândi este de a stoca cheile într-o listă de căutare și de a adăuga cheile în listă înainte de a le adăuga în dicționar ... nu este destul de tho.

0
adăugat
@Juan: nu există metoda .Last() pe KeyCollection
adăugat autor lomaxx, sursa
I didnt testa codul, dar metoda este documentată pe [MSDN] [1] poate o altă versiune cadru? [1]: msdn.microsoft.com/en-us/library/bb908406. aSPX
adăugat autor Juan, sursa
2 ani întârziere, dar ar putea ajuta pe cineva ... vezi răspunsul meu la postul lui Juan de mai jos. Ultima() este o metodă de extensie.
adăugat autor SuperOli, sursa

Modul în care ați formulat întrebarea mă determină să cred că int în dicționar conține poziția elementului în dicționar. Judecând din afirmația că cheile nu sunt stocate în ordinea în care sunt adăugate, dacă acest lucru este corect, ar însemna că tastele.Count (sau .Count - 1, dacă utilizați zero) ar trebui să fie încă este întotdeauna numărul cheii introduse ultima dată?

If that's correct, is there any reason you can't instead use Dictionary so that you can use mydict[ mydict.Keys.Count ]?

0
adăugat

Puteți utiliza un OrderedDictionary .

Reprezintă o colecție de cheie / valoare   perechi care sunt accesibile prin cheie   sau index.

0
adăugat
Erhm, după 19 upvotes, nimeni nu a menționat că OrderedDictionary încă nu permite să obțineți cheia prin index?
adăugat autor Lazlo, sursa
Puteți accesa o valoare cu un index întreg cu OrderedDictionary , dar nu cu System.Collections.Generic.SortedDictionary unde indexul trebuie să fie tasta t
adăugat autor Maxence, sursa

Puteți face întotdeauna acest lucru:

string[] temp = new string[mydict.count];
mydict.Keys.CopyTo(temp, 0)
int LastCount = mydict[temp[mydict.count - 1]]

Dar nu aș recomanda-o. Nu există nicio garanție că ultima cheie inserată va fi la sfârșitul matricei. Comanda pentru chei pe MSDN este nespecificată și poate fi modificată. În testul meu foarte scurt, se pare că este în ordinea inserării, dar ar fi mai bine să construiți o evidență corectă ca o stivă - așa cum sugerează (deși nu văd nevoia unui struct bazat pe alte instrucțiuni) - sau cache variabil unic dacă trebuie doar să cunoașteți ultima cheie.

0
adăugat

De ce nu extindeți clasa dicționarului pentru a adăuga o ultimă proprietate introdusă în cheie. Ceva de genul următorului?

public class ExtendedDictionary : Dictionary
{
    private int lastKeyInserted = -1;

    public int LastKeyInserted
    {
        get { return lastKeyInserted; }
        set { lastKeyInserted = value; }
    }

    public void AddNew(string s, int i)
    {
        lastKeyInserted = i;

        base.Add(s, i);
    }
}
0
adăugat
Eh? Nu, nu sunt(?)
adăugat autor Calanus, sursa
Setați lastKeyInserted la ultima valoare introdusă. Fie ați vrut să o setați la ultima cheie introdusă, fie aveți nevoie de nume mai bune pentru variabila și proprietatea.
adăugat autor Fantius, sursa

Cred că poți face ceva de genul ăsta, sintaxa ar putea fi greșită, nu a folosit C# de ceva timp Pentru a obține ultimul element

Dictionary.KeyCollection keys = mydict.keys;
string lastKey = keys.Last();

sau utilizați Max în loc de Ultima pentru a obține valoarea maximă, nu știu care dintre ele se potrivește mai bine codului.

0
adăugat
Încercați acest lucru pentru ultimul (atunci când utilizați un Dist evident :-) KeyValuePair last = oAuthPairs.Last (); dacă (kvp.Key! = last.Key) {_oauth_ParamString = _oauth_ParamString + "&"; }
adăugat autor Tim Windsor, sursa
Aș adăuga că, din moment ce "Last ()" este o metodă de extensie, ai avea nevoie de .NET Framework 3.5 și să adaugi "folosind System.Linq" în partea de sus a fișierului .cs.
adăugat autor SuperOli, sursa

In case you decide to use dangerous code that is subject to breakage, this extension function will fetch a key from a Dictionary according to its internal indexing (which for Mono and .NET currently appears to be in the same order as you get by enumerating the Keys property).

Este mult mai preferabil să folosiți Linq: dict.Keys.ElementAt (i) , dar această funcție va repeta O (N); următorul este O (1), dar cu o pedeapsă de performanță de reflecție.

using System;
using System.Collections.Generic;
using System.Reflection;

public static class Extensions
{
    public static TKey KeyByIndex(this Dictionary dict, int idx)
    {
        Type type = typeof(Dictionary);
        FieldInfo info = type.GetField("entries", BindingFlags.NonPublic | BindingFlags.Instance);
        if (info != null)
        {
            // .NET
            Object element = ((Array)info.GetValue(dict)).GetValue(idx);
            return (TKey)element.GetType().GetField("key", BindingFlags.Public | BindingFlags.Instance).GetValue(element);
        }
        // Mono:
        info = type.GetField("keySlots", BindingFlags.NonPublic | BindingFlags.Instance);
        return (TKey)((Array)info.GetValue(dict)).GetValue(idx);
    }
};
0
adăugat
Hmm, editarea pentru a îmbunătăți răspunsul a câștigat o scădere a valorii. Nu am făcut clar faptul că codul este (evident) îngrozitor și ar trebui să fie luat în considerare în consecință?
adăugat autor Glenn Slayden, sursa

După cum arată @Falanwe într-un comentariu, a face ceva de genul acesta este incorect :

int LastCount = mydict.Keys.ElementAt(mydict.Count -1);

nu ar trebui să depindă de ordinea tastelor dintr-un dicționar. Dacă aveți nevoie de comenzi, ar trebui să utilizați un OrderedDictionary , așa cum este sugerat în răspunsul . Celelalte răspunsuri de pe această pagină sunt interesante.

0
adăugat
Acest lucru este înfricoșător ... dar de ajutor pentru mine, deoarece am fost în căutarea pentru a confirma suspiciunea mea că nu poate conta pentru comanda! Multumesc @Falanwe
adăugat autor Charlie, sursa
pare să nu funcționeze cu HashTable System.Collections.ICollection "nu conține o definiție pentru 'ElementAt' și nici o metodă de extensie 'ElementAt' acceptând un prim argument de tipul 'System.Collections.ICollection' ar putea fi găsite
adăugat autor v.oddou, sursa
Pentru unii, ordinea nu este relevantă - doar faptul că ați trecut prin toate cheile.
adăugat autor Royi Mindel, sursa
@Falanwe De ce nu sortezi primul dicționar, astfel încât acesta să fie în ordinea necesară?
adăugat autor MGot90, sursa
Puteți folosi versiunea ElementAtOrDefault pentru a lucra cu o versiune excepțională.
adăugat autor Tarık Özgün Gün, sursa