Używam Dictionary<string, int>
gdzie int
jest liczba klucza.
Teraz muszę uzyskać dostęp do ostatnio włożonego klucza w słowniku, ale nie znam jego nazwy. Oczywista próba:
int LastCount = mydict[mydict.keys[mydict.keys.Count]];
nie działa, ponieważ Dictionary.Keys
nie implementuje [] -indexer.
Zastanawiam się tylko, czy istnieje podobna klasa? Myślałem o użyciu stosu, ale przechowuje on tylko ciąg. Mógłbym teraz stworzyć własną strukturę, a następnie użyć a Stack<MyStruct>
, ale zastanawiam się, czy istnieje inna alternatywa, zasadniczo Słownik, który implementuje [] -indexer w Keys?
c#
.net
dictionary
Michael Stum
źródło
źródło
Odpowiedzi:
Jak @Falanwe wskazuje w komentarzu, zrobienie czegoś takiego jest niepoprawne :
Nie powinieneś polegać na kolejności kluczy w słowniku. Jeśli potrzebujesz złożyć zamówienie, powinieneś użyć OrderedDictionary , jak sugeruje ta odpowiedź . Inne odpowiedzi na tej stronie również są interesujące.
źródło
HashTable
System.Collections.ICollection ”nie zawiera definicji elementu„ ElementAt ”i nie można znaleźć metody rozszerzającej„ ElementAt ”akceptującej pierwszy argument typu„ System.Collections.ICollection ”ElementAtOrDefault
wersji do pracy z wersją bez wyjątków.Dictionary<TKey,TValue>
dokumentacją stwierdza się, że „Kolejność kluczy w nieDictionary<TKey, TValue>.KeyCollection
jest określona”. Zlecenie jest niezdefiniowane, nie masz pewności, która pozycja jest na ostatniej pozycji (mydict.Count -1
)Możesz użyć OrderedDictionary .
źródło
Słownik to tablica z haszowaniem, więc nie masz pojęcia, w jakiej kolejności wstawiać!
Jeśli chcesz poznać ostatnio wstawiony klucz, sugerowałbym rozszerzenie Słownika o wartość LastKeyInserted.
Na przykład:
Napotkasz jednak problemy, gdy użyjesz,
.Remove()
więc aby temu zaradzić, będziesz musiał zachować uporządkowaną listę wstawionych kluczy.źródło
Dlaczego po prostu nie rozszerzysz klasy słownika, aby dodać ostatnią wstawioną właściwość klucza. Może coś takiego jak poniższe?
źródło
Zawsze możesz to zrobić:
Ale nie polecałbym tego. Nie ma gwarancji, że ostatni wstawiony klucz będzie na końcu tablicy. Sposób zamawiania kluczy w witrynie MSDN nie jest określony i może ulec zmianie. W moim bardzo krótkim teście wydaje się, że jest w kolejności wstawiania, ale lepiej byłoby budować w prawidłowej księgowości jak stos - jak sugerujesz (chociaż nie widzę potrzeby struktury opartej na inne instrukcje) - lub pamięć podręczną pojedynczej zmiennej, jeśli potrzebujesz tylko znać najnowszy klucz.
źródło
Myślę, że możesz zrobić coś takiego, składnia może być zła, od jakiegoś czasu nie używałeś C # Aby uzyskać ostatni element
lub użyj Max zamiast Last, aby uzyskać maksymalną wartość, nie wiem, który z nich lepiej pasuje do twojego kodu.
źródło
Zgadzam się z drugą częścią odpowiedzi Patryka. Nawet jeśli w niektórych testach wydaje się, że zachowuje kolejność wstawiania, dokumentacja (i normalne zachowanie słowników i skrótów) wyraźnie stwierdza, że kolejność jest nieokreślona.
Po prostu prosisz o kłopoty w zależności od kolejności kluczy. Dodaj własną księgowość (jak powiedział Patrick, tylko pojedyncza zmienna dla ostatniego dodanego klucza), aby mieć pewność. Nie daj się też skusić na wszystkie metody, takie jak Last i Max w słowniku, ponieważ są one prawdopodobnie związane z kluczowym komparatorem (nie jestem tego pewien).
źródło
W przypadku, gdy zdecydujesz się na użycie niebezpiecznego kodu, który może ulec uszkodzeniu, ta funkcja rozszerzenia pobierze klucz z a
Dictionary<K,V>
zgodnie z jego wewnętrznym indeksowaniem (które dla Mono i .NET wydaje się obecnie być w tej samej kolejności, jaką otrzymujesz przez wyliczenieKeys
właściwości ).O wiele lepiej jest używać Linq:,
dict.Keys.ElementAt(i)
ale ta funkcja będzie iterować O (N); Poniżej znajduje się O (1), ale z utratą odbicia.źródło
Jedną alternatywą byłby KeyedCollection, jeśli klucz jest osadzony w wartości.
Po prostu utwórz podstawową implementację w zapieczętowanej klasie do użycia.
Więc do zamiany
Dictionary<string, int>
(co nie jest dobrym przykładem, ponieważ nie ma jasnego klucza dla int).źródło
Sposób sformułowania pytania prowadzi mnie do wniosku, że int w słowniku zawiera „pozycję” elementu w słowniku. Sądząc po stwierdzeniu, że klucze nie są przechowywane w kolejności, w jakiej zostały dodane, jeśli jest to poprawne, oznaczałoby to, że klucze.Count (lub .Count - 1, jeśli używasz od zera) powinny nadal zawsze jest numerem ostatnio wprowadzonego klucza?
Jeśli to prawda, czy jest jakiś powód, dla którego nie możesz zamiast tego użyć Dictionary <int, string>, aby użyć mydict [mydict.Keys.Count]?
źródło
Nie wiem, czy to zadziała, ponieważ jestem prawie pewien, że klucze nie są przechowywane w kolejności, w jakiej są dodawane, ale możesz rzucić KeysCollection na Listę, a następnie pobrać ostatni klucz na liście ... ale warto byłoby rzucić okiem.
Jedyną rzeczą, o której przychodzi mi do głowy, jest przechowywanie kluczy na liście wyszukiwania i dodawanie kluczy do listy przed dodaniem ich do słownika ... to nie jest ładne.
źródło
Aby rozwinąć post Danielsa i jego komentarze dotyczące klucza, ponieważ klucz i tak jest osadzony w wartości, możesz skorzystać z
KeyValuePair<TKey, TValue>
jako wartości. Głównym powodem tego jest to, że generalnie klucz niekoniecznie musi być bezpośrednio wyprowadzony z wartości.Wtedy wyglądałoby to tak:
Aby użyć tego jak w poprzednim przykładzie, wykonaj następujące czynności:
źródło
Słownik może nie być zbyt intuicyjny, jeśli chodzi o używanie indeksu jako odniesienia, ale podobne operacje można wykonywać z tablicą KeyValuePair :
dawny.
KeyValuePair<string, string>[] filters;
źródło
Możesz także użyć SortedList i jego odpowiednika Generic. Te dwie klasy i wspomniana w odpowiedzi Andrew Petersa OrderedDictionary to klasy słownikowe, w których dostęp do elementów można uzyskać zarówno za pomocą indeksu (pozycji), jak i klucza. Jak korzystać z tych klas, możesz znaleźć: SortedList Class , SortedList Generic Class .
źródło
Usługa UserVoice programu Visual Studio udostępnia link do ogólnej implementacji OrderedDictionary przez dotmore.
Ale jeśli potrzebujesz tylko par klucz / wartość według indeksu i nie potrzebujesz pobierać wartości za pomocą kluczy, możesz użyć jednej prostej sztuczki. Zadeklaruj jakąś klasę ogólną (nazwałem ją ListArray) w następujący sposób:
Możesz również zadeklarować to za pomocą konstruktorów:
Na przykład, czytasz niektóre pary klucz / wartość z pliku i po prostu chcesz przechowywać je w kolejności, w jakiej zostały odczytane, aby później uzyskać je według indeksu:
Jak być może zauważyłeś, niekoniecznie możesz mieć tylko pary klucz / wartość w swojej ListArray. Tablice elementów mogą mieć dowolną długość, na przykład tablice postrzępione.
źródło