Kaip rūšiuoti žodyną pagal vertę?

Dažnai turiu rūšiuoti žodyną, kurį sudaro raktai ir vertės pagal vertę. Pavyzdžiui, turiu žodžių ir atitinkamų dažnių, kuriuos noriu užsisakyti pagal dažnį.

Yra „ SortedList , kuris tinka vienai vertei (pvz., Dažniui), kurį noriu priskirti šiam žodžiui.

RūšiuotiDictionary užsako raktą, o ne vertę. Kai kurie kreipiasi į pasirinktą klasę , bet ar yra švaresnis būdas?

640
02 авг. nustatė Kalid 02 rug. 2008-08-02 03:40 '08 at 3:40 2008-08-02 03:40
@ 17 atsakymų

Naudoti:

 using System.Linq.Enumerable; ... List<KeyValuePair<string, string>> myList = aDictionary.ToList(); myList.Sort( delegate(KeyValuePair<string, string> pair1, KeyValuePair<string, string> pair2) { return pair1.Value.CompareTo(pair2.Value); } ); 

Kadangi nukreipiate .NET 2.0 ar naujesnę versiją, galite ją supaprastinti lambda sintaksėje - tai yra lygiavertė, bet trumpesnė. Jei taikėte .NET 2.0, šią sintaksę galite naudoti tik tada, jei naudojate kompiuteryją iš „Visual Studio 2008“ (arba naujesnės versijos).

 var myList = aDictionary.ToList(); myList.Sort((pair1,pair2) => pair1.Value.CompareTo(pair2.Value)); 
445
02 авг. Atsakymas Leon Bambrick 02 rug. 2008-08-02 04:15 '08 at 4:15 2008-08-02 04:15

Naudokite LINQ:

 Dictionary<string, int> myDict = new Dictionary<string, int>(); myDict.Add("one", 1); myDict.Add("four", 4); myDict.Add("two", 2); myDict.Add("three", 3); var sortedDict = from entry in myDict orderby entry.Value ascending select entry; 

Jis taip pat suteiks daugiau lankstumo, nes galite pasirinkti geriausius 10, 20 10% ir kt. Arba, jei naudojate savo žodinio dažnio indeksą į type-ahead , taip pat galite įtraukti „ StartsWith .

463
04 авг. atsakymas duotas caryden 04 rug . 2008-08-04 18:22 '08, 18:22 pm 2008-08-04 18:22
 var ordered = dict.OrderBy(x => x.Value); 
161
11 нояб. atsakymas pateikiamas seanlinmt 11 nov. 2010-11-11 20:16 '10, 20:16, 2010-11-11 20:16

Žvelgdami aplink ir naudojant kai kurias C # 3.0 funkcijas, galime tai padaryti:

 foreach (KeyValuePair<string,int> item in keywordCounts.OrderBy(key=> key.Value)) { // do something with item.Key and item.Value } 

Tai yra švariausias būdas, kurį aš mačiau ir panašus į rubinų metodas apdoroti maišus.

145
02 авг. atsakymas pateikiamas Kalid 02 rug. 2008-08-02 03:43 '08 at 3:43 2008-08-02 03:43

Jūs galite rūšiuoti žodyną pagal vertę ir išsaugoti ją atgal (taip, kad, žiūrėdami į ją, reikšmės eina tvarka):

 dict = dict.OrderBy(x => x.Value).ToDictionary(x => x.Key, x => x.Value); 

Žinoma, tai gali būti neteisinga, tačiau ji veikia.

136
22 июня '11 в 13:26 2011-06-22 13:26 atsakymą pateikė Matt Frear , birželio 22 d. 11 val. 16.00 val. 2011-06-22 13:26

Aukštu lygiu jūs neturite kito pasirinkimo eiti per visą žodyną ir pažvelgti į kiekvieną vertę.

Gal tai padeda: http://bytes.com/forum/thread563638.html Kopijuoti / įklijuoti iš John Timney:

 Dictionary<string, string> s = new Dictionary<string, string>(); s.Add("1", "a Item"); s.Add("2", "c Item"); s.Add("3", "b Item"); List<KeyValuePair<string, string>> myList = new List<KeyValuePair<string, string>>(s); myList.Sort( delegate(KeyValuePair<string, string> firstPair, KeyValuePair<string, string> nextPair) { return firstPair.Value.CompareTo(nextPair.Value); } ); 
55
02 авг. Michael Stum atsakymas rugpjūčio 02 d 2008-08-02 03:47 '08 at 3:47 2008-08-02 03:47

Bet kokiu atveju, jūs niekada negalėsite rūšiuoti žodyno. Jie nėra užsakomi. Žodžių garantijos yra tai, kad raktų ir vertybių kolekcijos yra pasikartojančios, o vertės gali būti gaunamos pagal indeksą arba raktą, tačiau nėra jokios konkrečios tvarkos garantijos. Todėl į sąrašą turėsite įvesti pavadinimo porą.

21
20 дек. Atsakymą pateikė Roger Willcocks 20 d. 2008-12-20 01:47 '08 ne 1:47 2008-12-20 01:47

Jūs nerūšiuojate žodyno įrašų. .NET žodyno klasė įgyvendinama kaip maišos lentelė - ši duomenų struktūra nėra suskirstyta pagal apibrėžimą.

Jei norite sugebėti kartoti per savo kolekciją (raktu), turite naudoti „SortedDictionary“, kuri yra įgyvendinama kaip dvejetainis paieškos medis.

Tačiau jūsų atveju šaltinio struktūra neturi reikšmės, nes ji yra rūšiuojama pagal kitą lauką. Jūs vis dar turite jį surūšiuoti pagal dažnį ir įdėti į naują kolekciją, surūšiuotą pagal atitinkamą lauką (dažnį). Todėl šiame rinkinyje dažniai yra raktai, o žodžiai - vertybės. Kadangi daugelis žodžių gali turėti tokį patį dažnį (ir jūs jį naudosite kaip raktą), negalite naudoti nei žodyno, nei „SortedDictionary“ (jiems reikia unikalių raktų). Tai palieka jus su „SortedList“.

Aš nesuprantu, kodėl jūs primygtinai reikalaujate išlaikyti nuorodą į pagrindinio / pirmojo žodyno šaltinio elementą.

Jei jūsų kolekcijoje esantys objektai turėjo sudėtingesnę struktūrą (daugiau laukų), ir jums reikėjo sugebėti juos veiksmingai pasiekti / rūšiuoti, naudodami kelis skirtingus laukus kaip raktus. Jums gali prireikti pasirinktinės duomenų struktūros, kurią sudarys pagrindinė saugykla, kuri palaiko O (1) įterpimą ir ištrynimą (LinkedList) ir kelias indeksavimo struktūras - žodynus / rūšiuojamus žodynus / rūšiuojamus sąrašus. Šie indeksai naudos vieną iš sudėtingo klasės laukų kaip raktą ir rodyklę / nuorodą į „LinkedListNode“ „LinkedList“ kaip vertę.

Norint sinchronizuoti indeksus su pagrindine kolekcija („LinkedList“), jums reikės koordinuoti intarpus ir ištrinimus, ir manau, kad trynimas būtų gana brangus. Tai panaši į tai, kaip duomenų bazė indeksuoja darbą - jie yra fantastiški ieškant, tačiau jie tampa našta, kai reikia atlikti daug operacijų ir ištrynimų.

Visa tai yra pateisinama tik tuo atveju, jei ketinate atlikti didelį apdorojimą. Jei jums reikia juos rodyti tik po rūšiavimo pagal dažnį, galite tiesiog sukurti (anoniminių) numerių sąrašą:

 var dict = new SortedDictionary<string, int>(); // ToDo: populate dict var output = dict.OrderBy(e => e.Value).Select(e => new {frequency = e.Value, word = e.Key}).ToList(); foreach (var entry in output) { Console.WriteLine("frequency:{0}, word: {1}",entry.frequency,entry.word); } 
14
13 дек. Atsakymą pateikė Zar Shardan gruodžio 13 d. 2012-12-13 09:19 '12 9:19 2012-12-13 09:19

Arba, jei norite smagiai, galite naudoti tam tikrą LINQ plėtinį:

 var dictionary = new Dictionary<string, int> { { "c", 3 }, { "a", 1 }, { "b", 2 } }; dictionary.OrderBy(x => x.Value) .ForEach(x => Console.WriteLine("{0}={1}", x.Key,x.Value)); 
10
30 июня '10 в 14:12 2010-06-30 14:12 Atsakymas pateikiamas mitui birželio 30, 10, 14:12 2010-06-30 14:12

Rūšiuoti reikšmes

Rodo, kaip rūšiuoti vertes žodyną. Mes matome konsolės programą, kurią galite kompiliuoti ir paleisti „Visual Studio“. Jis prideda raktinių žodžių žodynui, o tada juos rūšiuoja pagal jų reikšmes. Atminkite, kad žodyno egzemplioriai iš pradžių nėra surūšiuoti. Prašyme naudojame LINING užsakymo raktinį žodį.

Elementas OrderBy Programa, kuri rūšiuoja žodyną [C #]

 using System; using System.Collections.Generic; using System.Linq; class Program { static void Main() { // Example dictionary. var dictionary = new Dictionary<string, int>(5); dictionary.Add("cat", 1); dictionary.Add("dog", 0); dictionary.Add("mouse", 5); dictionary.Add("eel", 3); dictionary.Add("programmer", 2); // Order by values. // ... Use LINQ to specify sorting by value. var items = from pair in dictionary orderby pair.Value ascending select pair; // Display results. foreach (KeyValuePair<string, int> pair in items) { Console.WriteLine("{0}: {1}", pair.Key, pair.Value); } // Reverse sort. // ... Can be looped over in the same way as above. items = from pair in dictionary orderby pair.Value descending select pair; } } 

Išeiti

 dog: 0 cat: 1 programmer: 2 eel: 3 mouse: 5 
10
20 июля '12 в 12:49 2012-07-20 12:49 atsakymą pateikė lasitha edirisooriya liepos 20 d., 12 val. 12:49 2012-07-20 12:49
 Dictionary<string, string> dic= new Dictionary<string, string>(); var ordered = dic.OrderBy(x => x.Value); return ordered.ToDictionary(t => t.Key, t => t.Value); 
10
20 июля '15 в 14:01 2015-07-20 14:01 atsakymą pateikė mrfazolka, liepos 20 d. 15, 14:01 2015-07-20 14:01

Rūšiuoti „ SortedDictionary sąrašą, kad prisijungtumėte prie „ ListView valdymo naudojant VB.NET:

 Dim MyDictionary As SortedDictionary(Of String, MyDictionaryEntry) MyDictionaryListView.ItemsSource = MyDictionary.Values.OrderByDescending(Function(entry) entry.MyValue) Public Class MyDictionaryEntry ' Need Property for GridViewColumn DisplayMemberBinding Public Property MyString As String Public Property MyValue As Integer End Class 

XAML:

 <ListView Name="MyDictionaryListView"> <ListView.View> <GridView> <GridViewColumn DisplayMemberBinding="{Binding Path=MyString}" Header="MyStringColumnName"></GridViewColumn> <GridViewColumn DisplayMemberBinding="{Binding Path=MyValue}" Header="MyValueColumnName"></GridViewColumn> </GridView> </ListView.View> </ListView> 
9
23 апр. BSalita atsakymas balandžio 23 d 2010-04-23 12:36 '10, 12:36 PM 2010-04-23 12:36

Kiti atsakymai yra geri, jei norite, kad „laikinas“ sąrašas būtų surūšiuotas pagal vertę. Tačiau, jei norite, kad žodynas būtų surūšiuotas pagal Key , kuris automatiškai sinchronizuojamas su kitu žodynu, suskirstytu pagal Value , galite naudoti Bijection<K1, K2> klasę .

Bijection<K1, K2> leidžia jums inicijuoti kolekciją su dviem egzistuojančiais žodynais, todėl, jei norite, kad vienas iš jų būtų nerūšiuotas ir norite, kad kitas būtų surūšiuotas, galite sukurti savo „bijection“ kodą, pvz.

 var dict = new Bijection<Key, Value>(new Dictionary<Key,Value>(), new SortedDictionary<Value,Key>()); 

IDictionary<> galite naudoti kaip bet kokį įprastą žodyną (jis įgyvendina IDictionary<> ), tada skambina dict.Inverse kad gautumėte „atvirkštinį“ žodyną, kuris yra rūšiuojamas pagal „ Value .

Bijection<K1, K2> yra „ Loyc.Collections.dll“ dalis , bet jei norite, galite tiesiog nukopijuoti šaltinio kodą į savo projektą.

Pastaba Jei yra keletas to paties vertės raktų, jūs negalite naudoti „ Bijection , tačiau galite rankiniu būdu sinchronizuoti tarp įprastų BMultiMap<Value,Key> Dictionary<Key,Value> ir BMultiMap<Value,Key> .

5
26 февр. atsakymas pateikiamas Qwertie 26 vasario mėn. 2016-02-26 10:15 '16 at 10:15 am 2016-02-26 10:15

Lengviausias būdas gauti rūšiuojamą žodyną yra naudoti įmontuotą „ SortedDictionary klasę:

 //Sorts sections according to the key value stored on "sections" unsorted dictionary, which is passed as a constructor argument System.Collections.Generic.SortedDictionary<int, string> sortedSections = null; if (sections != null) { sortedSections = new SortedDictionary<int, string>(sections); } 

sortedSections bus surūšiuota sections versija

5
03 апр. Alex Ruiz atsakymas 03 balandžio. 2010-04-03 01:36 '10 ne 1:36 2010-04-03 01:36

Tarkime, kad turime tokį žodyną

  Dictionary<int, int> dict = new Dictionary<int, int>(); dict.Add(21,1041); dict.Add(213, 1021); dict.Add(45, 1081); dict.Add(54, 1091); dict.Add(3425, 1061); sict.Add(768, 1011); 

1) galite naudoti temporary dictionary to store values as :

  Dictionary<int, int> dctTemp = new Dictionary<int, int>(); foreach (KeyValuePair<int, int> pair in dict.OrderBy(key => key.Value)) { dctTemp .Add(pair.Key, pair.Value); } 
4
02 февр. Atsakymą pateikė Akshay Kapoor 02 vasaris. 2015-02-02 13:46 '15, 13:46, 2015-02-02 13:46

Atsižvelgiant į tai, kad turite žodyną, galite jį rūšiuoti tiesiai pagal savo vertes, naudodami vieną žemiau pateiktą linijinę liniją:

 var x = (from c in dict orderby c.Value.Order ascending select c).ToDictionary(c => c.Key, c=>c.Value); 
-2
01 июня '14 в 1:30 2014-06-01 01:30 atsakymą pateikė agresija birželio 1 d. 14 d. 1:30 2014-06-01 01:30

Jūs galite rūšiuoti žodyną pagal vertę ir gauti rezultatą žodyną naudodami šį kodą:

 Dictionary <<string, string>> ShareUserNewCopy = ShareUserCopy.OrderBy(x => x.Value).ToDictionary(pair => pair.Key, pair => pair.Value); 
-2
24 июля '12 в 15:24 2012-07-24 15:24 atsakymas pateikiamas pawan Kumar liepos 24 d., 12 val. 15:24 2012-07-24 15:24