Często muszę sortować słownik, składający się z kluczy i wartości, według wartości. Na przykład mam skrót słów i odpowiednie częstotliwości, które chcę uporządkować według częstotliwości.
Jest coś, SortedList
co jest dobre dla pojedynczej wartości (powiedzmy częstotliwości), którą chcę odwzorować z powrotem na słowo.
SortedDictionary zamówienia według klucza, a nie wartości. Niektórzy uciekają się do klasy niestandardowej , ale czy istnieje czystszy sposób?
c#
.net
sorting
dictionary
Kalid
źródło
źródło
IComparer
, który załatwi sprawę (prawda, że akceptuje klucz do porównania, ale za pomocą klucza można uzyskać wartość). ;-)Odpowiedzi:
Posługiwać się:
Ponieważ celujesz w .NET 2.0 lub nowszy, możesz uprościć to w składni lambda - jest to równoważne, ale krótsze. Jeśli celujesz w .NET 2.0, możesz użyć tej składni tylko wtedy, gdy używasz kompilatora z Visual Studio 2008 (lub nowszego).
źródło
myList.Sort((x,y)=>x.Value.CompareTo(y.Value));
IEnumerable
, więc możesz uzyskać posortowaną listę w następujący sposób:var mySortedList = myDictionary.OrderBy(d => d.Value).ToList();
Użyj LINQ:
Pozwoliłoby to również na dużą elastyczność, ponieważ możesz wybrać najwyższe 10, 20 10% itd. Lub jeśli używasz indeksu częstotliwości słów
type-ahead
, możesz również dołączyćStartsWith
klauzulę.źródło
IEnumerable<KeyValuePair<TKey, TValue>>
alboOrderedDictionary<TKey, TValue>
. Lub należy użyćSortedDictionary
od samego początku. W przypadku zwykłegoDictionary
MSDN wyraźnie stwierdza „Kolejność zwracania elementów jest niezdefiniowana”. Wygląda na to, że najnowsza edycja @ rythos42 jest winna. :).ToDictionary
- standardowe słowniki nie gwarantują sortowaniaźródło
Rozglądając się i korzystając z niektórych funkcji C # 3.0, możemy to zrobić:
Jest to najczystszy sposób, jaki widziałem i jest podobny do Ruby'ego do obsługi skrótów.
źródło
(for KeyValuePair<string, int> item in keywordCounts.OrderBy(key => key.Value) select item).ToDictionary(t => t.Key, t => t.Value)
- tylko mały dodatek do twojej odpowiedzi :) Dzięki, btw :)Możesz posortować słownik według wartości i zapisać go z powrotem do siebie (aby po przekroczeniu go wartości pojawiały się w kolejności):
Jasne, może nie być poprawne, ale działa.
źródło
Na wysokim poziomie nie masz innego wyjścia, jak przejść przez cały Słownik i spojrzeć na każdą wartość.
Może to pomaga: http://bytes.com/forum/thread563638.html Kopiowanie / wklejanie od Johna Timneya:
źródło
Zresztą nigdy nie będziesz w stanie posortować słownika. W rzeczywistości nie są zamówione. Gwarancje dla słownika polegają na tym, że kolekcje kluczy i wartości są iterowalne, a wartości można wyszukiwać według indeksu lub klucza, ale nie ma gwarancji na żadną konkretną kolejność. Dlatego musisz umieścić parę wartości nazwy na liście.
źródło
Nie sortujesz wpisów w Słowniku. Klasa słownika w .NET jest implementowana jako tablica mieszająca - tej struktury danych nie można z definicji sortować.
Jeśli chcesz mieć możliwość iteracji w swojej kolekcji (według klucza) - musisz użyć SortedDictionary, który jest zaimplementowany jako drzewo wyszukiwania binarnego.
W twoim przypadku jednak struktura źródłowa nie ma znaczenia, ponieważ jest posortowana według innego pola. Nadal będziesz musiał posortować dane według częstotliwości i umieścić je w nowej kolekcji posortowanej według odpowiedniego pola (częstotliwości). W tej kolekcji częstotliwości to klucze, a słowa to wartości. Ponieważ wiele słów może mieć tę samą częstotliwość (i użyjesz go jako klucza), nie możesz używać ani słownika, ani SortedDictionary (wymagają one unikatowych kluczy). To pozostawia Ci SortedList.
Nie rozumiem, dlaczego nalegasz na utrzymanie linku do oryginalnej pozycji w głównym / pierwszym słowniku.
Jeśli obiekty w Twojej kolekcji miały bardziej złożoną strukturę (więcej pól) i musiałeś mieć możliwość skutecznego dostępu / sortowania ich przy użyciu kilku różnych pól jako kluczy - prawdopodobnie potrzebowałbyś niestandardowej struktury danych, która składałaby się z głównej pamięci, która obsługuje wstawianie i usuwanie O (1) (LinkedList) oraz kilka struktur indeksujących - Dictionaries / SortedDictionaries / SortedLists. Indeksy te wykorzystałyby jedno z pól z twojej klasy złożonej jako klucz oraz wskaźnik / referencję do LinkedListNode w LinkedList jako wartość.
Trzeba koordynować wstawiania i usuwania, aby utrzymać synchronizację indeksów z kolekcją główną (LinkedList), a usuwanie byłoby dość drogie. Jest to podobne do działania indeksów baz danych - są fantastyczne do wyszukiwania, ale stają się obciążeniem, gdy trzeba wykonać wiele wstawień i usunięć.
Wszystko powyższe jest uzasadnione tylko wtedy, gdy zamierzasz przeprowadzić ciężkie przetwarzanie. Jeśli potrzebujesz je wyprowadzić tylko raz posortowane według częstotliwości, możesz po prostu utworzyć listę (anonimowych) krotek:
źródło
źródło
Lub dla zabawy możesz użyć jakiegoś rozszerzenia LINQ:
źródło
Sortowanie
SortedDictionary
listy do powiązania zListView
kontrolką za pomocą VB.NET:XAML:
źródło
Najłatwiejszym sposobem uzyskania posortowanego słownika jest użycie wbudowanej
SortedDictionary
klasy:sortedSections
będzie zawierać posortowaną wersjęsections
źródło
SortedDictionary
sortuj według kluczy. OP chce sortować według wartości.SortedDictionary
nie pomaga w tym przypadku.sorteddictionary()
zawsze wygrywałem o co najmniej 1 mikrosekundę, i jest to o wiele łatwiejsze do zarządzania (ponieważ narzut związany z przekształcaniem go z powrotem w coś, z czym łatwo można się współdziałać i którym zarządza się podobnie do słownika, wynosi 0 (to już jest asorteddictionary
)).Inne odpowiedzi są dobre, jeśli wszystko, czego chcesz, to mieć „tymczasową” listę posortowaną według wartości. Jeśli jednak chcesz posortować słownik,
Key
który automatycznie synchronizuje się z innym sortowanym słownikiemValue
, możesz użyć tejBijection<K1, K2>
klasy .Bijection<K1, K2>
pozwala na zainicjowanie kolekcji za pomocą dwóch istniejących słowników, więc jeśli chcesz, aby jeden z nich był nieposortowany, a drugi chcesz posortować, możesz utworzyć swój bijection za pomocą kodu podobnego doMożesz użyć
dict
dowolnego zwykłego słownika (implementujeIDictionary<K, V>
), a następnie wywołać,dict.Inverse
aby uzyskać posortowany słownik „odwrotny”Value
.Bijection<K1, K2>
jest częścią Loyc.Collections.dll , ale jeśli chcesz, możesz po prostu skopiować kod źródłowy do własnego projektu.Uwaga : Jeśli istnieje wiele kluczy o tej samej wartości, nie możesz ich użyć
Bijection
, ale możesz ręcznie zsynchronizować pomiędzy zwykłymDictionary<Key,Value>
a aBMultiMap<Value,Key>
.źródło
Załóżmy, że mamy słownik jako
1) możesz użyć
temporary dictionary to store values as
:źródło
Właściwie w C #, słowniki nie mają metod sort (), ponieważ bardziej interesuje cię sortowanie według wartości, nie możesz uzyskać wartości, dopóki nie podasz im klucza, krótko mówiąc, musisz iterować za ich pomocą, używając LINQ's Sortuj według,
możesz zrobić jedną sztuczkę,
lub
zależy również od rodzaju przechowywanych wartości, czy
jest pojedynczy (jak łańcuch, int) czy wielokrotny (jak Lista, Tablica, klasa zdefiniowana przez użytkownika),
jeśli pojedynczy możesz zrobić listę, to zastosuj sort.
jeśli klasa zdefiniowana przez użytkownika, to klasa ta musi implementować IComparable
ClassName: IComparable<ClassName>
i przesłonić,compareTo(ClassName c)
ponieważ są one szybsze niż LINQ i bardziej obiektowe.źródło
Wymagana przestrzeń nazw:
using System.Linq;
Sortuj według:
Sortuj według Asc:
źródło
Możesz posortować słownik według wartości i uzyskać wynik w słowniku, korzystając z poniższego kodu:
źródło
Biorąc pod uwagę, że masz słownik, możesz posortować je bezpośrednio według wartości, używając jednego linijki:
źródło