Koks yra geriausias būdas kartoti per C # žodyną?

Mačiau kelis skirtingus būdus, kaip pakartoti C # žodyną. Ar yra standartinis būdas?

1677
26 сент. nustatė Jake Stewart 26 sept. 2008-09-26 21:20 '08 at 9:20 pm 2008-09-26 21:20
@ 20 atsakymų
2547
26 сент. atsakymą pateikė Pablo Fernandez 26 sep. 2008-09-26 21:22 '08 at 9:22 pm 2008-09-26 21:22

Jei bandote naudoti bendrąjį žodyną C #, kaip jei naudojote asociatyviąją masyvą kita kalba:

 foreach(var item in myDictionary) { foo(item.Key); bar(item.Value); } 

Arba, jei jums reikia tik pereiti per raktų rinkimą, naudokite

 foreach(var item in myDictionary.Keys) { foo(item); } 
border=0

Ir galiausiai, jei domitės tik vertybėmis:

 foreach(var item in myDictionary.Values) { foo(item); } 

(Atkreipkite dėmesį, kad var raktinis žodis yra neprivaloma C # 3.0 ir aukštesnės versijos funkcija, taip pat galite naudoti tikslų raktų / vertybių tipą čia)

528
26 сент. atsakymą pateikė Jokūbas 26 sep. 2008-09-26 21:22 '08 at 9:22 pm 2008-09-26 21:22

Kai kuriais atvejais jums gali prireikti skaitiklio, kuris gali būti pateiktas kilpui įgyvendinti. Šiuo tikslu LINQ teikia „ ElementAt , kuri leidžia:

 for (int index = 0; index < dictionary.Count; index++) { var item = dictionary.ElementAt(index); var itemKey = item.Key; var itemValue = item.Value; } 
98
10 марта '11 в 23:44 2011-03-10 23:44 atsakymą pateikė Maurício Fedatto kovo 11 d. 11 val. 23:44 2011-03-10 23:44

Priklausomai nuo to, ar esate už raktų ar vertybių ...

Iš MSDN žodyno <(iš ​​<(TKey, TValue>)>) Klasės aprašymas:

 // When you use foreach to enumerate dictionary elements, // the elements are retrieved as KeyValuePair objects. Console.WriteLine(); foreach( KeyValuePair<string, string> kvp in openWith ) { Console.WriteLine("Key = {0}, Value = {1}", kvp.Key, kvp.Value); } // To get the values alone, use the Values property. Dictionary<string, string>.ValueCollection valueColl = openWith.Values; // The elements of the ValueCollection are strongly typed // with the type that was specified for dictionary values. Console.WriteLine(); foreach( string s in valueColl ) { Console.WriteLine("Value = {0}", s); } // To get the keys alone, use the Keys property. Dictionary<string, string>.KeyCollection keyColl = openWith.Keys; // The elements of the KeyCollection are strongly typed // with the type that was specified for dictionary keys. Console.WriteLine(); foreach( string s in keyColl ) { Console.WriteLine("Key = {0}", s); } 
71
26 сент. atsakymą pateikė J Healy 26 sep. 2008-09-26 21:27 '08 at 9:27 pm 2008-09-26 21:27

Paprastai prašymas „geriausio kelio“ be konkretaus konteksto yra klausimas, kas yra geriausia spalva.

Viena vertus, yra daug spalvų ir nėra geresnės spalvos. Tai priklauso nuo poreikio ir dažnai dėl skonio.

Kita vertus, yra daug būdų, kaip kartoti per žodyną C #, ir nėra geresnio būdo. Tai priklauso nuo poreikio ir dažnai dėl skonio.

Lengviausias būdas

 foreach (var kvp in items) { // key is kvp.Key doStuff(kvp.Value) } 

Jei jums reikia tik vertės (leidžia jį pavadinti, lengviau skaitoma nei kvp.Value ).

 foreach (var item in items.Values) { doStuff(item) } 

Jei jums reikia konkrečios rūšiavimo tvarkos

Paprastai pradedantiesiems stebisi ta eilutė, kurioje yra žodynas.

LINQ pateikia glaustą sintaksę, kuri leidžia nurodyti užsakymą (ir daug daugiau), pavyzdžiui:

 foreach (var kvp in items.OrderBy(kvp => kvp.Key)) { // key is kvp.Key doStuff(kvp.Value) } 

Vėlgi, jums gali prireikti tik vertės. LINQ taip pat pateikia trumpą sprendimą:

  • iteracija tiesiai į vertę (leidžia jums jį pavadinti, lengviau skaitoma nei kvp.Value )
  • bet surūšiuoti pagal raktus

Čia jis yra:

 foreach (var item in items.OrderBy(kvp => kvp.Key).Select(kvp => kvp.Value)) { doStuff(item) } 

Šiuose pavyzdžiuose yra daug pavyzdžių, kaip naudoti realiame pasaulyje. Jei jums nereikia konkretaus užsakymo, tiesiog laikykitės „lengviausio būdo“ (žr. Aukščiau)!

48
10 авг. Stéphane Gourichon atsakymas, rugpjūčio 10 d. 2015-08-10 14:15 '15, 14:15, 2015-08-10 14:15

Sakyčiau, kad foreach yra standartinis būdas, nors jis akivaizdžiai priklauso nuo to, ko ieškote.

 foreach(var value in my_dictionary) { ... } 

Ar tai ko ieškote?

30
26 сент. atsakymą pateikė George Mauer 26 sep. 2008-09-26 21:22 '08 at 9:22 pm 2008-09-26 21:22

Yra daug galimybių. Mano asmeninis mėgstamiausias yra KeyValuePair

 Dictionary<string,object> myDictionary = new Dictionary<string,object>(); //Populate your dictionary here Foreach (KeyValuePair<string,object> kvp in myDictionary) { //Do some interesting things; } 

Taip pat galite naudoti raktų ir vertės rinkinius.

21
26 сент. atsakymą pateikė „ Theo 26 sep“. 2008-09-26 21:22 '08 at 9:22 pm 2008-09-26 21:22

Taip pat galite tai išbandyti dideliuose žodynuose, skirtuose apdoroti daugiamandeliu būdu.

 dictionary .AsParallel() .ForAll(pair => { // Process pair.Key and pair.Value here }); 
19
11 июня '15 в 16:32 2015-06-11 16:32 atsakymas pateiktas Onur birželio 11 d., 15 val. 16:32 2015-06-11 16:32

Suprantu, kad šis klausimas jau turėjo daug atsakymų, bet norėjau atlikti nedidelį tyrimą.

Žodyno iteracija gali būti gana lėta, palyginti su iteracija per kažką panašaus į masyvą. Mano bandymuose iteracija per masyvą užtruko 0.015003 sekundes, o iteracija per žodyną (su tuo pačiu elementų skaičiumi) užtruko 0.0365073 sekundes, o tai 2,4 karto ilgiau! Nors aš pastebėjau daug didesnius skirtumus. Palyginimui, sąrašas buvo kažkur viduryje tarp 0,00215043 sekundžių.

Tačiau tai panaši į obuolių ir apelsinų palyginimą. Noriu pasakyti, kad iteracija per žodynus yra lėta.

Žodynai yra optimizuoti paieškai, todėl, turint omenyje, aš sukūriau du metodus. Vienas paprasčiausiai pasisako, kitas kartoja raktus, tada ieško.

  public static string Normal(Dictionary<string, string> dictionary) { string value; int count = 0; foreach (var kvp in dictionary) { value = kvp.Value; count++; } return "Normal"; } 

Tai įkelia raktus ir kartoja juos vietoj jų (aš taip pat bandžiau ištraukti raktus į [] liniją, tačiau skirtumas buvo nereikšmingas.

  public static string Keys(Dictionary<string, string> dictionary) { string value; int count = 0; foreach (var key in dictionary.Keys) { value = dictionary[key]; count++; } return "Keys"; } 

Šiame pavyzdyje įprastas testavimo testas užėmė 0,0310062, o pagrindinė versija - 0,2205441. Visų raktų pakrovimas ir visų paieškų kartojimas yra akivaizdžiai lėčiau!

Paskutinį testą aš pakartojau dešimt kartų, kad išsiaiškintumėte, ar čia yra kokių nors privalumų (šiuo metu buvau tik smalsu):

Jis naudoja „RunTest“ metodą, jei jis padeda suprasti, kas vyksta.

  private static string RunTest<T>(T dictionary, Func<T, string> function) { DateTime start = DateTime.Now; string name = null; for (int i = 0; i < 10; i++) { name = function(dictionary); } DateTime end = DateTime.Now; var duration = end.Subtract(start); return string.Format("{0} took {1} seconds", name, duration.TotalSeconds); } 

Čia įprasta foreach run užtruko 0,2820564 sekundes (apie dešimt kartų ilgiau nei vienas iteravimas, kaip tikėtasi). Klavišų iteracija užtruko 2,2249449 sekundes.

Redaguota, kad pridėtumėte: perskaičius keletą kitų atsakymų, paklausiau, kas atsitiktų, jei vietoj žodyno naudoju žodyną. Šiame pavyzdyje matrica užtruko 0.0120024 sekundes, sąrašas - 0.0185037 sekundės, o žodynas - 0,0465093 sekundės. Tikslinga tikėtis, kad duomenų tipas paveiks žodyno lėtumą.

Kokios mano išvados ?

  • Venkite pakartotinio žodyno, jei įmanoma, jie yra žymiai lėtesni nei iteracijos per masyvą su tais pačiais duomenimis.
  • Jei norite eiti per žodyną, nebandykite būti pernelyg protingas, nors galite padaryti daug lėčiau nei naudojant standartinį foreach metodą.
17
30 июля '14 в 13:54 2014-07-30 13:54 Atsakymą pateikė „ Liath “ liepos 14 d. 14 val. 13:54 2014-07-30 13:54

Jūs siūlėte kartoti

 Dictionary<string,object> myDictionary = new Dictionary<string,object>(); //Populate your dictionary here foreach (KeyValuePair<string,object> kvp in myDictionary) { //Do some interesting things; } 

FYI, foreach neveikia, jei vertė yra tipo objektas.

9
28 окт. Khushi atsakė spalio 28 d 2009-10-28 23:49 '09 at 11:49 PM 2009-10-28 23:49

Paprasčiausia žodyno kartojimo forma:

 foreach(var item in myDictionary) { Console.WriteLine(item.Key); Console.WriteLine(item.Value); } 
8
02 окт. atsakymas pateikiamas Ron 02 Oct 2016-10-02 07:00 '16 at 7:00 2016-10-02 07:00

Kartais, jei jums reikia tik vertybių, kurias reikia įtraukti į sąrašą, naudokite žodynų reikšmių rinkinį:

 foreach(var value in dictionary.Values) { // do something with entry.Value only } 

Pranešė šis pranešimas, kuriame sakoma, kad tai yra greičiausias būdas: http://alexpinsker.blogspot.hk/2010/02/c-fastest-way-to-iterate-over.html

6
02 июля '14 в 4:55 2014-07-02 04:55 atsakymas suteiktas 2 liepos 14 d. 4:55 2014-07-02 04:55

Radau šį metodą MSDN žodyno bazės klasės dokumentuose:

 foreach (DictionaryEntry de in myDictionary) { //Do some stuff with de.Value or de.Key } 

Tai buvo vienintelė, su kuria galėjau normaliai funkcionuoti klasėje, kurią paveldėjo iš žodyno bazės.

5
18 февр. Atsakymą pateikė Zannjaminderson vasario 18 d. 2009-02-18 02:51 '09 at 2:51 am 2009-02-18 02:51

Įprastas būdas kartoti žodyną pagal oficialų MSDN dokumentaciją:

 foreach (DictionaryEntry entry in myDictionary) { //Read entry.Key and entry.Value here } 
3
28 июля '16 в 13:58 2016-07-28 13:58 atsakymas pateikiamas Nick'o liepos 28, 16 d. 13:58 2016-07-28 13:58

Aš naudosiu .NET 4.0+ ir pateiksiu atnaujintą atsakymą į pradžioje priimtą versiją:

 foreach(var entry in MyDic) { // do something with entry.Value or entry.Key } 
3
02 окт. atsakymas duotas yazanpro 02 okt. 2014-10-02 02:17 '14, 14:17 am 2014-10-02 02:17

Jei, pvz., Norite kartoti per numatytųjų nustatymų rinkinį, manau, kad galite įgyvendinti IEnumerable <>, kur T yra vertimo objekto tipas žodyne ir „tai“ yra žodynas.

 public new IEnumerator<T> GetEnumerator() { return this.Values.GetEnumerator(); } 
2
09 дек. atsakymas pateikiamas mzirino 09 dec. 2008-12-09 07:16 '08, 07:16, 2008-12-09 07:16

Tiesiog norėjau pridėti 2 centus, nes dauguma atsakymų yra susiję su foreach kilpa. Pažvelkite į šį kodą:

 Dictionary<String, Double> myProductPrices = new Dictionary<String, Double>(); //Add some entries to the dictionary myProductPrices.ToList().ForEach(kvP => { kvP.Value *= 1.15; Console.Writeline(String.Format("Product '{0}' has a new price: {1} $", kvp.Key, kvP.Value)); }); 

Tai pridėjo papildomą skambutį į „.ToList ()“, galbūt bus šiek tiek pagerėjęs našumas (kaip nurodyta čia foreach vs someList.Foreach () {} ). iš viso.

Taip pat atkreipkite dėmesį, kad negalite priskirti reikšmės „Vertė“ savybei foreach kilpoje. Kita vertus, jūs taip pat galite manipuliuoti „raktu“, galbūt vykdydami susidursite su sunkumais.

Kai tik norite nuskaityti raktus ir reikšmes, galite naudoti ir „IEnumerable“.

 var newProductPrices = myProductPrices.Select(kvp => new { Name = kvp.Key, Price = kvp.Value * 1.15 } ); 
1
16 сент. atsakymas Alexui 16 sep. 2016-09-16 19:03 '16 at 7:03 pm 2016-09-16 19:03
 var dictionary = new Dictionary<string, int> { { "Key", 12 } }; var aggregateObjectCollection = dictionary.Select( entry => new AggregateObject(entry.Key, entry.Value)); 
0
28 мая '15 в 18:00 2015-05-28 18:00 Atsakymą pateikė „ Pixar “ gegužės 28 d., 15 val. 18:00 2015-05-28 18:00

Naudodami .NET Framework 4.7 galite naudoti skaidymą

 var fruits = new Dictionary<string, int>(); ... foreach (var (fruit, number) in fruits) { Console.WriteLine(fruit + ": " + number); } 

Kad šis kodas veiktų žemesnėse C # versijose, pridėkite „ System.ValueTuple NuGet package ir parašykite kažkur

 public static class MyExtensions { public static void Deconstruct<T1, T2>(this KeyValuePair<T1, T2> tuple, out T1 key, out T2 value) { key = tuple.Key; value = tuple.Value; } } 
0
17 окт. Atsakyti Pavel 17 okt. 2017-10-17 18:18 '17 at 18:18 2017-10-17 18:18

Ne standartinis būdas, bet darbas:

 Dictionary<string, int> dict = new Dictionary<string, int> { {"Foo", 1 }, {"Bar", 2 } }; dict.Select(kvp => { Console.WriteLine(kvp.Key + " - " + kvp.Value.ToString()); return kvp; }).Count(); 
0
05 июля '15 в 16:36 2015-07-05 16:36 atsakymas duotas liepos 5 d. 15 d. 16:36 pm 2015-07-05 16:36

Kiti klausimai apie žymų arba Užduoti klausimą