Přístup k Dictionary.Keys klíč prostřednictvím číselného indexu

hlasů
136

Já jsem za použití Dictionary<string, int>, kde intje počet klíče.

Teď potřebuji pro přístup k naposledy vložen klíč uvnitř slovníku, ale já nevím, jméno jeho. Zřejmý pokus:

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

nefunguje, protože Dictionary.Keysneimplementuje [] -indexer.

Jen by mě zajímalo, jestli existuje nějaký podobný třída? Přemýšlel jsem o použití Stack, ale to jen ukládá řetězec. Mohl bych nyní vytvořit svůj vlastní struct a pak použít Stack<MyStruct>, ale zajímalo by mě, jestli tam je další alternativou, v podstatě slovník, který implementuje [] -indexer na klávesách?

Položena 07/08/2008 v 01:51
zdroj uživatelem
V jiných jazycích...                            


15 odpovědí

hlasů
204

Jako @Falanwe poukazuje na to v komentáři, dělat něco takového je nesprávný :

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

Byste neměli záviset na pořadí klíčů ve slovníku. Pokud potřebujete pořadí byste měli používat OrderedDictionary , jak je navrženo v této odpovědi . Ostatní odpovědi na této stránce jsou zajímavé také.

Odpovězeno 19/01/2011 v 14:21
zdroj uživatelem

hlasů
56

Můžete použít OrderedDictionary .

Představuje soubor párů klíč / hodnota, které jsou přístupné pomocí klíče nebo indexu.

Odpovězeno 08/08/2008 v 02:23
zdroj uživatelem

hlasů
16

Slovník je Hash Table, takže nemáte tušení řádově vložení!

Chcete-li vědět, poslední vloženým klíčem Osobně bych doporučoval rozšíření slovníku zahrnout LastKeyInserted hodnotu.

Např:

public MyDictionary<K, T> : IDictionary<K, T>
{
    private IDictionary<K, T> _InnerDictionary;

    public K LastInsertedKey { get; set; }

    public MyDictionary()
    {
        _InnerDictionary = new Dictionary<K, T>();
    }

    #region Implementation of IDictionary

    public void Add(KeyValuePair<K, T> item)
    {
        _InnerDictionary.Add(item);
        LastInsertedKey = item.Key;

    }

    public void Add(K key, T value)
    {
        _InnerDictionary.Add(key, value);
        LastInsertedKey = key;
    }

    .... rest of IDictionary methods

    #endregion

}

Budete se dostanete do problémů se však při použití .Remove(), takže k překonání tohoto, budete muset držet seřazený seznam klíčů vložených.

Odpovězeno 16/04/2009 v 15:09
zdroj uživatelem

hlasů
8

Proč ne jen rozšířit třídu slovníku přidat do vloženého majetku poslední klíč. Něco jako následující možná?

public class ExtendedDictionary : Dictionary<string, int>
{
    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);
    }
}
Odpovězeno 07/08/2008 v 12:15
zdroj uživatelem

hlasů
6

Dalo by se vždy to následujícím způsobem:

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

Ale já bych nedoporučoval. Neexistuje žádná záruka, že poslední vložený klíč bude na konci pole. Řazení na klíče na webu MSDN je určen, a mohou se změnit. V mém velmi krátkém testu, se zdá být v pořádku vkládání, ale vy byste se lépe budovy v řádné účetnictví jako zásobníku - jak naznačují (i když nevidím potřebu struct na základě svých další příkazy) - nebo jedna variabilní vyrovnávací paměti stačí-li znát nejnovější klíč.

Odpovězeno 07/08/2008 v 02:13
zdroj uživatelem

hlasů
5

Myslím, že můžete udělat něco takového, syntaxe by mohlo být špatně, havent používané C # chvíli Chcete-li získat poslední položky

Dictionary<string, int>.KeyCollection keys = mydict.keys;
string lastKey = keys.Last();

nebo použít Max namísto Poslední získat maximální hodnotu, nevím, který z nich se hodí váš kód lépe.

Odpovězeno 07/08/2008 v 02:18
zdroj uživatelem

hlasů
4

Jednou z alternativ by KeyedCollection v případě, že klíč je zakotven v hodnotě.

Stačí vytvořit základní implementaci v zapečetěné třídě používat.

Takže nahradit Dictionary<string, int>(což není velmi dobrým příkladem, protože není jasné klíčem k int).

private sealed class IntDictionary : KeyedCollection<string, int>
{
    protected override string GetKeyForItem(int item)
    {
        // The example works better when the value contains the key. It falls down a bit for a dictionary of ints.
        return item.ToString();
    }
}

KeyedCollection<string, int> intCollection = new ClassThatContainsSealedImplementation.IntDictionary();

intCollection.Add(7);

int valueByIndex = intCollection[0];
Odpovězeno 20/07/2011 v 01:45
zdroj uživatelem

hlasů
4

Souhlasím s druhou částí Patrika odpovědi. Dokonce i když v některých testech se zdá, aby objednávku vložení dokumentace (a normální chování pro slovníky a hash) výslovně uvádí uspořádání není specifikován.

Jste jen koleduje o malér v závislosti na uspořádání kláves. Přidejte svůj vlastní účetnictví (jak řekl Patrick, jen jediná proměnná pro poslední přidané klíče) být jistý. Také nemusí být v pokušení všemi způsoby, jako poslední a Maxe na slovníku jako ty jsou pravděpodobně ve vztahu ke klíčovým komparátor (nejsem si jistý, že).

Odpovězeno 07/08/2008 v 03:38
zdroj uživatelem

hlasů
3

V případě, že se rozhodnete použít nebezpečný kód, který je předmětem zlomení, toto rozšíření funkce stáhne klíč od A Dictionary<K,V>podle své vnitřní indexování (což pro Mono a .NET v současné době se zdá být ve stejném pořadí, jak se dostanete podle výčet Keysmajetku ).

Je mnohem výhodnější použít LINQ: dict.Keys.ElementAt(i), ale funkce bude iterovat O (N); následující je O (1), ale s trestem výkonu reflexe.

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

public static class Extensions
{
    public static TKey KeyByIndex<TKey,TValue>(this Dictionary<TKey, TValue> dict, int idx)
    {
        Type type = typeof(Dictionary<TKey, TValue>);
        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);
    }
};
Odpovězeno 12/04/2010 v 05:44
zdroj uživatelem

hlasů
3

Tak, jak si zní otázka mě vede k přesvědčení, že int ve slovníku obsahuje „pozici“ položky, na slovníku. Soudě podle tvrzení, že klíče nejsou uloženy v pořadí, v jakém jste přidali, je-li to správně, to by znamenalo, že keys.Count (nebo .Count - 1, pokud používáte od nuly) by stále vždy je číslo poslední zadané klíče?

Jestli je to správné, je nějaký důvod, proč není možné místo toho použít slovník <int, string>, takže můžete použít mydict [mydict.Keys.Count]?

Odpovězeno 07/08/2008 v 03:40
zdroj uživatelem

hlasů
2

Slovník nemusí být velmi intuitivní pro používání indexu pro referenci, ale můžete mít podobné operace s řadou KeyValuePair :

ex. KeyValuePair<string, string>[] filters;

Odpovězeno 06/04/2016 v 21:15
zdroj uživatelem

hlasů
2

Můžete také použít SortedList a jeho Generic protějšek. Tyto dvě třídy a v Andrew Peters odpovědi zmínil OrderedDictionary jsou třídy slovník, ve kterém mohou být položky přístupné pomocí indexu (pozice), stejně jako klíčem. Jak používat tyto třídy najdete tyto položky: SortedList třída , SortedList Generic třídy .

Odpovězeno 25/03/2015 v 18:13
zdroj uživatelem

hlasů
2

Expandovat na Daniels sloupku a jeho připomínek týkajících klíče, protože klíč je obsažen přímo v hodnotě stejně, můžete se uchýlit k pomocí KeyValuePair<TKey, TValue>jako hodnotu. Hlavním úvaha je to, že, obecně platí, že klíč nemusí být nutně přímo odvodit z hodnoty.

Pak to by vypadat takto:

public sealed class CustomDictionary<TKey, TValue>
  : KeyedCollection<TKey, KeyValuePair<TKey, TValue>>
{
  protected override TKey GetKeyForItem(KeyValuePair<TKey, TValue> item)
  {
    return item.Key;
  }
}

Chcete-li použít jako v předchozím případě, že vy:

CustomDictionary<string, int> custDict = new CustomDictionary<string, int>();

custDict.Add(new KeyValuePair<string, int>("key", 7));

int valueByIndex = custDict[0].Value;
int valueByKey = custDict["key"].Value;
string keyByIndex = custDict[0].Key;
Odpovězeno 20/07/2011 v 10:21
zdroj uživatelem

hlasů
2

Já nevím, jestli by to fungovalo, protože jsem si jistý, že klíče nejsou uloženy v pořadí, v jakém jsou přidány, ale mohli jste odevzdaných KeysCollection do seznamu a pak se poslední klíč v seznamu ... ale to by stálo za to podívat.

Jediná věc, co mě napadlo je k ukládání klíčů v seznamu vyhledávání a přidat klíče do seznamu před přidat do slovníku ... to není dost tho.

Odpovězeno 07/08/2008 v 02:15
zdroj uživatelem

hlasů
1

Visual Studio UserVoice dává odkaz na generické implementace OrderedDictionary od dotmore.

Ale pokud si jen potřebujete získat páry klíč / hodnota indexem a nemusíte dostat hodnot klíčů, můžete použít jeden jednoduchý trik. Prohlásit nějakou generickou třídu (Zavolal jsem ji ListArray) takto:

class ListArray<T> : List<T[]> { }

Můžete také deklarovat s konstruktéry:

class ListArray<T> : List<T[]>
{
    public ListArray() : base() { }
    public ListArray(int capacity) : base(capacity) { }
}

Například si přečíst některé páry klíč / hodnota ze souboru a chci ukládat v pořadí, v jakém byly čtení tak, aby si je později indexu:

ListArray<string> settingsRead = new ListArray<string>();
using (var sr = new StreamReader(myFile))
{
    string line;
    while ((line = sr.ReadLine()) != null)
    {
        string[] keyValueStrings = line.Split(separator);
        for (int i = 0; i < keyValueStrings.Length; i++)
            keyValueStrings[i] = keyValueStrings[i].Trim();
        settingsRead.Add(keyValueStrings);
    }
}
// Later you get your key/value strings simply by index
string[] myKeyValueStrings = settingsRead[index];

Jak jste si možná všimli, můžete mít ne nutně jen dvojice klíč / hodnota v ListArray. Položka pole mohou být jakékoliv délky, stejně jako v členitém pole.

Odpovězeno 03/11/2016 v 08:42
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more