Vraag Wat is de beste manier om een ​​woordenboek te herhalen?


Ik heb een paar verschillende manieren gezien om een ​​woordenboek in C # te herhalen. Is er een standaardmanier?


1944
2017-09-26 18:20


oorsprong


antwoorden:


foreach(KeyValuePair<string, string> entry in myDictionary)
{
    // do something with entry.Value or entry.Key
}

2892
2017-09-26 18:22



Als u een generiek woordenboek in C # probeert te gebruiken, zoals u een associatieve array in een andere taal zou gebruiken:

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

Of gebruik als u alleen de verzameling toetsen wilt herhalen

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

En als laatste, als u alleen geïnteresseerd bent in de waarden:

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

(Houd er rekening mee dat de var trefwoord is een optionele C # 3.0 en hoger functie, u zou hier ook het exacte type van uw sleutels / waarden kunnen gebruiken)


643
2017-09-26 18:22



In sommige gevallen hebt u mogelijk een teller nodig die kan worden geleverd door de implementatie van de lus. Daarvoor biedt LINQ ElementAt waarmee het volgende mogelijk is:

for (int index = 0; index < dictionary.Count; index++) {
  var item = dictionary.ElementAt(index);
  var itemKey = item.Key;
  var itemValue = item.Value;
}

107
2018-03-10 20:44



Afhankelijk van of je op zoek bent naar de sleutels of de waarden ...

Van het MSDN Dictionary(TKey, TValue) Klasse beschrijving:

// 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);
}

74
2017-09-26 18:27



Over het algemeen is het vragen om "de beste manier" zonder een specifieke context hetzelfde als vragen wat de beste kleur is.

Aan de ene kant zijn er veel kleuren en er is geen beste kleur. Het hangt af van de behoefte en vaak ook van smaak.

Aan de andere kant zijn er veel manieren om een ​​woordenboek te herhalen in C # en er is geen beste manier. Het hangt af van de behoefte en vaak ook van smaak.

Meest eenvoudige manier

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

Als u alleen de waarde nodig heeft (hiermee kunt u hem bellen item, leesbaarder dan kvp.Value).

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

Als u een specifieke sorteervolgorde nodig hebt

Over het algemeen zijn beginners verbaasd over volgorde van opsomming van een woordenboek.

LINQ biedt een beknopte syntaxis waarmee u de volgorde (en vele andere zaken) kunt opgeven, bijvoorbeeld:

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

Nogmaals, je hebt misschien alleen de waarde nodig. LINQ biedt ook een beknopte oplossing voor:

  • itereer direct op de waarde (laat toe om het te noemen item, leesbaarder dan kvp.Value)
  • maar gesorteerd op de toetsen

Hier is het:

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

Er zijn veel meer praktische voorbeelden van deze voorbeelden. Als u geen specifieke bestelling nodig heeft, houdt u zich gewoon aan de "meest eenvoudige manier" (zie hierboven)!


55
2017-08-10 11:15



Ik zou zeggen dat voor iedereen de standaardmanier is, hoewel het natuurlijk afhankelijk is van wat je zoekt

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

Is dat waar je naar op zoek bent?


36
2017-09-26 18:22



U kunt dit ook proberen op grote woordenboeken voor multithreaded verwerking.

dictionary
.AsParallel()
.ForAll(pair => 
{ 
    // Process pair.Key and pair.Value here
});

27
2018-06-11 13:32



Er zijn veel opties. Mijn persoonlijke favoriet is door KeyValuePair

Dictionary<string, object> myDictionary = new Dictionary<string, object>();
// Populate your dictionary here

foreach (KeyValuePair<string,object> kvp in myDictionary)
{
     // Do some interesting things
}

U kunt ook de collecties Keys and Values ​​gebruiken


22
2017-09-26 18:22



Ik waardeer dat deze vraag al veel reacties heeft gehad, maar ik wilde een beetje onderzoek doen.

Itereren over een woordenboek kan nogal traag zijn in vergelijking met itereren over zoiets als een array. In mijn tests duurde een iteratie over een array 0,015003 seconden terwijl een iteratie boven een woordenboek (met hetzelfde aantal elementen) 0,0365073 seconden duurde, dat is 2,4 keer zo lang! Hoewel ik veel grotere verschillen heb gezien. Ter vergelijking lag een lijst ergens tussenin op 0.00215043 seconden.

Dat is echter hetzelfde als het vergelijken van appels en sinaasappels. Mijn punt is dat itereren over woordenboeken traag is.

Woordenboeken zijn geoptimaliseerd voor lookups, dus met dat in het achterhoofd heb ik twee methoden gemaakt. Men doet eenvoudigweg een foreach, de ander herhaalt de toetsen en kijkt dan op.

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

    return "Normal";
}

Deze laadt de toetsen en itereert in plaats daarvan (ik heb ook geprobeerd de toetsen in een reeks [] te trekken, maar het verschil was te verwaarlozen.

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";
}

In dit voorbeeld nam de normale foreach-test 0,0310062 en de versie van de toetsen 0,2205441. Het laden van alle sleutels en het herhalen van alle lookups 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 u helpt te visualiseren wat er aan de hand is.

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);
}

Hier nam de normale foreach-run 0.2820564 seconden (ongeveer tien keer langer dan een enkele iteratie - zoals je zou verwachten). De iteratie over de toetsen kostte 2.2249449 seconden.

Bewerkt om toe te voegen: Als ik enkele van de andere antwoorden las, vroeg ik me af wat er zou gebeuren als ik Dictionary gebruikte in plaats van Dictionary. In dit voorbeeld nam de array 0,0120024 seconden, de lijst 0,0185037 seconden en het woordenboek 0,0465093 seconden. Het is redelijk om te verwachten dat het gegevenstype een verschil maakt voor hoeveel langzamer het woordenboek is.

Wat zijn mijn conclusies?

  • Vermijd iterating over een woordenboek als je kunt, ze zijn aanzienlijk trager dan iteratie over een array met dezelfde gegevens.
  • Als je ervoor kiest om een ​​woordenboek te herhalen, probeer dan niet te slim te zijn, hoewel je langzamer veel slechter kunt doen dan met de standaard foreach-methode.

22
2017-07-30 10:54