c# - Wat is de beste manier om te itereren over een woordenboek?
Wat is de beste manier om te itereren over een woordenboek?
Ik heb een paar verschillende manieren gezien om over een woordenboek in C # te herhalen. Is er een standaard manier?
2, Autoriteit 23%
Als u probeert een generiek woordenboek in C # zoals u een associatieve array in een andere taal te gebruiken:
of, als u alleen maar over de verzameling sleutels nodig hebt,
en ten slotte, als u alleen geïnteresseerd bent in de waarden:
(Let op: de vartrefwoord is een optionele C # 3.0 en bovenstaande functie, u kunt hier ook het exacte type van uw sleutels / waarden gebruiken)
3, Autoriteit 4%
In sommige gevallen heeft u mogelijk een teller nodig die kan worden verstrekt door de implementatie van de lus. Daarvoor biedt LINQ ElementAtwaarmee het volgende mogelijk is:
4, Autoriteit 3%
Afhankelijk van of je op zoek bent naar de sleutels of de waarden…
Van de MSDN Dictionary(TKey, TValue)Klasbeschrijving:
Over het algemeen is vragen naar 'de beste manier' zonder een specifieke context hetzelfde als vragen
wat is de beste kleur?
Enerzijds zijn er veel kleuren en is er geen beste kleur. Het hangt af van de behoefte en vaak ook van de smaak.
Aan de andere kant zijn er veel manieren om een Dictionary in C# te herhalen en er is geen beste manier. Het hangt af van de behoefte en vaak ook van de smaak.
Meest eenvoudige manier
Als je alleen de waarde nodig hebt (maakt het mogelijk om het itemte noemen, leesbaarder dan kvp.Value).
Als je een specifieke sorteervolgorde nodig hebt
In het algemeen zijn beginners verbaasd over de volgorde van opsomming van een woordenboek.
LINQ biedt een beknopte syntaxis waarmee de volgorde (en vele andere dingen) kan worden gespecificeerd, bijvoorbeeld:
Ook hier heb je misschien alleen de waarde nodig. LINQ biedt ook een beknopte oplossing voor:
rechtstreeks op de waarde herhalen (maakt het mogelijk om het itemte noemen, leesbaarder dan kvp.Value)
maar gesorteerd op de toetsen
Er zijn nog veel meer praktijkvoorbeelden die u kunt gebruiken op basis van deze voorbeelden.
Als je geen specifieke bestelling nodig hebt, blijf dan gewoon op de "meest eenvoudige manier" (zie hierboven)!
Ik zou zeggen dat foreach de standaardmanier is, hoewel het natuurlijk afhangt van wat je zoekt
Is dat wat u zoekt?
C # 7.0 geïntroduceerd Deconstructors en als u .NET Core 2.0 + Applicatie, de structuur KeyValuePair<>bevatten reeds een Deconstruct()voor u. Dus je kunt doen:
U kunt ook dit proberen op grote woordenboeken voor multithreaded verwerking.
Ik stel deze vraag heeft al veel reacties gehad, maar ik wilde gooien in een beetje onderzoek.
itereren over een woordenboek kan nogal traag zijn in vergelijking met het itereren over iets als een array. In mijn tests een iteratie over een array nam 0.015003 seconden terwijl een iteratie over een woordenboek (met hetzelfde aantal elementen) nam 0,0365073 seconden dat is 2,4 keer zo lang! Hoewel ik veel grotere verschillen hebben gezien. Ter vergelijking was een lijst ergens tussen in 0.00215043 seconden.
Maar dat is als appels met peren vergelijken. Mijn punt is dat de iteratie dan woordenboeken is traag.
Woordenboeken zijn geoptimaliseerd voor zoekopdrachten, dus met dat in gedachten heb ik twee methoden gemaakt. De een doet gewoon een foreach, de ander herhaalt de toetsen en kijkt dan op.
Deze laadt de toetsen en herhaalt ze in plaats daarvan (ik heb ook geprobeerd de toetsen in een string te trekken[] maar het verschil was te verwaarlozen.
Bij dit voorbeeld kostte de normale foreach-test 0,0310062 en de sleutelversie 0,2205441. Het laden van alle sleutels en het herhalen van alle zoekopdrachten is duidelijk VEEL langzamer!
Voor een laatste test heb ik mijn iteratie tien keer uitgevoerd om te zien of er voordelen zijn aan het gebruik van de toetsen hier (op dit punt was ik gewoon nieuwsgierig):
Hier is de RunTest-methode als dat je helpt te visualiseren wat er aan de hand is.
Hier duurde de normale foreach-run 0,2820564 seconden (ongeveer tien keer langer dan een enkele iteratie, zoals je zou verwachten). De iteratie over de toetsen duurde 2.2249449 seconden.
Bewerkt om toe te voegen:
Toen ik enkele van de andere antwoorden las, vroeg ik me af wat er zou gebeuren als ik Dictionary zou gebruiken in plaats van Dictionary. In dit voorbeeld duurde de array 0,0120024 seconden, de lijst 0,0185037 seconden en de woordenlijst 0,0465093 seconden. Het is redelijk om te verwachten dat het gegevenstype een verschil maakt in hoeveel langzamer het woordenboek is.
Vermijd het herhalen van een woordenboek als je kunt, ze zijn aanzienlijk langzamer dan het herhalen van een array met dezelfde gegevens erin.
Als je ervoor kiest om een woordenboek te herhalen, probeer dan niet te slim te zijn, hoewel je langzamer zou kunnen doen dan het gebruik van de standaard foreach-methode.
Er zijn tal van opties. Mijn persoonlijke favoriet is van KeyValuePair
U kunt ook de verzamelingen sleutels en waarden gebruiken
Zoals reeds aangegeven in dit answer, KeyValuePair<TKey, TValue>implementeert een Deconstruct-methode vanaf .NET Core 2.0, .NET Standard 2.1 en .NET Framework 5.0 (preview).
Hiermee is het mogelijk om te herhalen via een woordenboek in een KeyValuePairagnostische manier:
Met .NET Framework 4.7Men kan Ontbinding
Om deze code te laten werken aan lagere C # -versies, voeg System.ValueTuple NuGet packagetoe en schrijf ergens
Als C # 7 kunt u objecten in variabelen deconstrueren. Ik geloof dat dit de beste manier is om over een woordenboek te herhalen.
Maak een uitbreidingsmethode op KeyValuePair<TKey, TVal>DAT DECONSTUMTS IT:
Herven over een Dictionary<TKey, TVal>op de volgende manier
U heeft hieronder voorgesteld om te herhalen
Ter info, foreachwerkt niet als de waarde van het type object is.
Eenvoudigste vorm om een woordenboek te herhalen:
Gebruik C# 7en voeg deze extensiemethodetoe aan elk project van uw oplossing:
En gebruik deze eenvoudige syntaxis
Of deze, zo je wilt
In plaats van de traditionele
De extension-methode transformeert de KeyValuePairvan uw IDictionary<TKey, TValue>In een sterk getypt tuple, zodat u deze nieuwe comfortabele syntaxis kunt gebruiken.
Het converteert – de vereiste woordenboekinvoering naar tuples, dus het converteert het hele woordenboek niet naar tuples, dus er zijn geen prestatiebepalen.
Er is slechts een kleine kosten die de uitbreidingsmethode oproepen voor het maken van een tuplein vergelijking met het gebruik van de KeyValuePairrechtstreeks, wat geen probleem zou moeten zijn als u de KeyValuePair'S EIGENSCHAPPEN KeyEN ValueNAAR NIEUWE LOOPVARIABELEN.
In de praktijk past deze nieuwe syntaxis past heel goed voor de meeste gevallen, behalve voor ultra-high-performance scenario's met een laag niveau, waar u nog steeds de mogelijkheid hebt om het gewoon niet op die specifieke plek te gebruiken.
Controleer dit: MSDN Blog – Nieuwe functies in C # 7
foreachis het snelst en als u alleen over ___.Values, is het ook sneller
Ik weet dat dit een heel oude vraag is, maar ik heb enkele uitbreidingsmethoden gemaakt die nuttig kunnen zijn:
Op deze manier kan ik code als volgt schrijven:
Ik vond deze methode in de documentatie voor de klasse DictionaryBase op MSDN:
Dit was de enige die ik correct kon laten functioneren in een klas die geërfd was van de DictionaryBase.
Soms, als je alleen de waarden nodig hebt om te inventariseren, gebruik dan de waardeverzameling van het woordenboek:
Gemeld door dit bericht waarin staat dat dit de snelste methode is:
http://alexpinsker.blogspot.hk/2010 /02/c-fastest-way-to-iterate-over.html
Ik heb het voordeel van .NET 4.0+ en geef een bijgewerkt antwoord op de oorspronkelijk geaccepteerde One:
De standaardmanier om te itereren boven een woordenboek, volgens de officiële documentatie op MSDN is:
Ik schreef een extensie om over een woordenboek te lussen.
Dan kunt u
Indien zeggen, u wilt standaard over de waardencollectie herhalen, ik geloof dat u Ienumerable & LT; & GT;, waarbij T het type van het waardenobject in het Woordenboek is, en "dit" is een woordenboek.
Als u voor lus wilt gebruiken, kunt u dit doen:
wilde gewoon mijn 2 cent toevoegen, omdat de meeste antwoorden betrekking hebben op foreach-lus.
Bekijk alstublieft de volgende code:
Hoewel dit een extra aanroep van '.ToList()' toevoegt, kan er een lichte prestatieverbetering zijn (zoals hier aangegeven foreach vs someList.Foreach(){}),
vooral bij het werken met grote woordenboeken en parallel werken is geen optie / heeft helemaal geen effect.
Houd er ook rekening mee dat u geen waarden kunt toewijzen aan de eigenschap 'Value' binnen een foreach-lus. Aan de andere kant kun je de 'sleutel' ook manipuleren, waardoor je mogelijk in de problemen komt tijdens runtime.
Als u alleen sleutels en waarden wilt "lezen", kunt u ook IEnumerable.Select() gebruiken.
Het beste antwoord is natuurlijk: Gebruik geen exact woordenboek als je van plan bent erover te herhalen– zoals Vikas Gupta al zei in de discussie onder de vraag. Maar die discussie, aangezien deze hele thread nog steeds verrassend goede alternatieven mist. Een daarvan is:
SortedList<string, string> x = new SortedList<string, string>();
x.Add("key1", "value1");
x.Add("key2", "value2");
x["key3"] = "value3";
foreach( KeyValuePair<string, string> kvPair in x )
Console.WriteLine($"{kvPair.Key}, {kvPair.Value}");
Waarom veel mensen het beschouwen als een codegeur van het herhalen van een woordenboek (bijv. door foreach(KeyValuePair<,>):
Het is nogal verrassend, maar er is een beetje aangehaald, maar basisprincipe van Clean Coding:
"Express intentie!"
Robert C. Martin schrijft in "Cleane Code": "Namen kiezen die de intentie onthullen". Uiteraard is dit te zwak. "Express (onthullen) Intent met elke coderingsbeslissing" zou beter zijn. Mijn formulering. Ik mis een goede eerste bron, maar ik weet zeker dat er …
Een gerelateerd principe is "principe van minstens verrassing " (= Principe van minst verbaasd ).
Waarom is dit gerelateerd aan het herhalen van een woordenboek? Een woordenboek kiezen, drukt de intentie uit om een ​​gegevensstructuur te kiezen die is gemaakt voor het vinden van gegevens per sleutel . Tegenwoordig zijn er zoveel alternatieven in .NET, als u wilt herhalen via sleutel / waardeparen die u niet nodig hebt deze kruk.
Bovendien: als u over iets herhaalt, moet u iets onthullen over hoe de items (te zijn) bestellen en naar verwachting worden besteld!
AFAIK, Dictionary heeft geen specificatie over het bestellen (alleen implementatie-specifieke conventies).
Sorteerlijst : Als uw verzameling niet te groot wordt, zou een eenvoudige oplossing zijn om SortedList & LT;, & GT; wat u ook volledige indexering van sleutel / waardeparen geeft.
Microsoft heeft een lang artikel over het vermelden en uitleggen van passende collecties:
Slaged Collection
Om het belangrijkste te vermelden: KeyedCollection & LT;, & GT; en SortedDictionary & LT;, & GT; .
SortedDictionary & LT;, & GT; Is een beetje sneller dan sorteerlijst voor Oly-invoeging als het groot wordt, maar mist indexering en is alleen nodig als O (log n) voor het invoegen wordt bijgevoegd over andere bewerkingen. Als je echt o (1) nodig hebt voor het invoegen en accepteren van langzamere iteratie in ruil, moet je blijven bij Simple Dictionary & LT;, & GT;.
Uiteraard is er geen gegevensstructuur die het snelst is voor elke mogelijke operatie.
Bovendien is er ImmutablesSortedDICTIONARIAIRE & LT;, & GT;
En als een gegevensstructuur niet precies is wat u nodig heeft, dan afgeleid van woordenboek & lt;, & GT; of zelfs van het nieuwe concurrentdictionary & lt;, & GT; en voeg expliciete iteratie / sorteerfuncties toe!
Naast de hoogste rangs-posten waar een discussie is tussen het gebruik van
Het meest compleet is het volgende omdat u het woordenboektype van de initialisatie kunt zien, KVP is KeyvaluEpair