Jaki jest najlepszy sposób na iterację słownika? [zamknięte]

zamknięte . To pytanie jest oparte na opinii . Obecnie nie przyjmuje odpowiedzi.

chcesz poprawić to pytanie? Zaktualizuj pytanie, aby mogło być odpowiedź z faktami i cytatami przez edytując ten post .

Zamknięte 17 dni temu .

Popraw to pytanie

Widziałem kilka różnych sposobów na iterację słownika w C#. Jest jakiś standardowy sposób?

Author: Uwe Keim, 2008-09-26

30 answers

foreach(KeyValuePair<string, string> entry in myDictionary)
{
    // do something with entry.Value or entry.Key
}
 3960
Author: Pablo Fernandez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-20 23:14:01

Jeśli próbujesz użyć słownika generycznego w C#, tak jak używasz tablicy asocjacyjnej w innym języku:

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

Lub, jeśli potrzebujesz tylko iteracji nad kolekcją kluczy, użyj

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

I na koniec, jeśli interesują Cię tylko wartości:

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

(zwróć uwagę, że słowo kluczowe var jest opcjonalną funkcją C# 3.0 i nowszych, możesz również użyć dokładnego typu kluczy / wartości tutaj)

 925
Author: Jacob,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-02 19:19:26

W niektórych przypadkach może być potrzebny licznik, który może być dostarczony przez implementację for-loop. W tym celu LINQ zapewnia ElementAt co umożliwia:

for (int index = 0; index < dictionary.Count; index++) {
  var item = dictionary.ElementAt(index);
  var itemKey = item.Key;
  var itemValue = item.Value;
}
 165
Author: Maurício Fedatto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-04 12:25:28

Zależy od tego, czy szukasz kluczy, czy wartości...

Z MSDN Dictionary(TKey, TValue) Opis klasy:

// 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);
}
 103
Author: J Healy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-06-24 11:11:26

Ogólnie rzecz biorąc, proszenie o "najlepszy sposób" bez konkretnego kontekstu jest jak proszenie jaki jest najlepszy kolor?

Jedna ręka, jest wiele kolorów i nie ma najlepszego koloru. To zależy od potrzeby, a często również od smaku.

Z drugiej strony, Istnieje wiele sposobów na iterację słownika w C# i nie ma najlepszego sposobu. To zależy od potrzeby, a często również od smaku.

Najprostszy sposób

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

Jeśli potrzebujesz tylko wartości (pozwala nazwać ją item, bardziej czytelną niż kvp.Value).

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

Jeśli potrzebujesz konkretnego porządku sortowania

Generalnie początkujący są zaskoczeni kolejnością wyliczania słownika.

LINQ zapewnia zwięzłą składnię, która pozwala określić porządek (i wiele innych rzeczy), np.:

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

Znowu możesz potrzebować tylko wartości. LINQ zapewnia również zwięzłe rozwiązanie do:

  • iteracja bezpośrednio na wartości (pozwala na wywołanie jej item, bardziej czytelna niż kvp.Value)
  • ale sortowane według kluczy

Oto jest:

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

Istnieje wiele innych rzeczywistych przypadków użycia, które możesz zrobić na podstawie tych przykładów. Jeśli nie potrzebujesz konkretnego zamówienia, po prostu trzymaj się" najprostszego sposobu " (patrz wyżej)!

 85
Author: Stéphane Gourichon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-06-03 12:28:39

Powiedziałbym, że foreach jest standardowym sposobem, choć oczywiście zależy to od tego, czego szukasz

foreach(var kvp in my_dictionary) {
  ...
}
Tego szukasz?
 56
Author: George Mauer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-17 15:59:56

C # 7.0 wprowadził Dekonstrukcje Jeśli używasz . Net Core 2.0+, struktura KeyValuePair<> zawiera już Deconstruct() dla Ciebie. Więc możesz zrobić:

var dic = new Dictionary<int, string>() { { 1, "One" }, { 2, "Two" }, { 3, "Three" } };
foreach (var (key, value) in dic) {
    Console.WriteLine($"Item [{key}] = {value}");
}
//Or
foreach (var (_, value) in dic) {
    Console.WriteLine($"Item [NO_ID] = {value}");
}
//Or
foreach ((int key, string value) in dic) {
    Console.WriteLine($"Item [{key}] = {value}");
}

Tutaj wpisz opis obrazka

 49
Author: Jaider,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-01-07 20:30:48

Możesz również wypróbować to w dużych słownikach do przetwarzania wielowątkowego.

dictionary
.AsParallel()
.ForAll(pair => 
{ 
    // Process pair.Key and pair.Value here
});
 44
Author: Onur,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-11 14:50:43

Doceniam, że to pytanie miało już wiele odpowiedzi, ale chciałem dorzucić trochę badań.

Iteracja nad słownikiem może być dość powolna w porównaniu z iteracją nad czymś takim jak tablica. W moich testach iteracja nad tablicą trwała 0.015003 sekundy, podczas gdy iteracja nad słownikiem (z taką samą liczbą elementów) trwała 0.0365073 sekundy, czyli 2.4 razy dłużej! Chociaż widziałem znacznie większe różnice. Dla porównania lista była gdzieś w od 0.00215043 sekund.

To jest jak porównywanie jabłek i pomarańczy. Chodzi mi o to, że iteracja słowników jest powolna.

Słowniki są zoptymalizowane pod kątem wyszukiwania, więc mając to na uwadze, stworzyłem dwie metody. Jeden po prostu wykonuje foreach, drugi iteracje kluczy, a następnie patrzy w górę.

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

    return "Normal";
}

Ten ładuje klucze i zamiast nich iteruje (próbowałem też wciągnąć Klucze do łańcucha [], ale różnica była znikoma.

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

Z w tym przykładzie normalny test foreach wyniósł 0.0310062, a wersja keys-0.2205441. Ładowanie wszystkich klawiszy i iteracja wszystkich wyszukiwań jest wyraźnie dużo wolniejsze!

Na ostatni test wykonałem swoją iterację dziesięć razy, aby sprawdzić, czy są jakieś korzyści z używania klawiszy tutaj (w tym momencie byłem po prostu ciekaw):

Oto najbrutalniejsza metoda, jeśli pomoże Ci to wyobrazić sobie, co się dzieje.

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

Tutaj normalny bieg foreach trwał 0.2820564 sekund (około dziesięć razy dłużej niż trwała pojedyncza iteracja - jak można się było spodziewać). 2.2249449 sekund

Edited To Add: Po przeczytaniu kilku innych odpowiedzi zadałem sobie pytanie, co by się stało, gdybym użył słownika zamiast słownika. W tym przykładzie tablica zajęła 0.0120024 sekund, lista 0.0185037 sekund, a Słownik 0.0465093 sekund. Rozsądnie jest oczekiwać, że typ danych ma wpływ na to, o ile słownik jest wolniejszy.

Co? Czy moje wnioski ?

  • unikaj iteracji nad słownikiem, jeśli możesz, są one znacznie wolniejsze niż iteracja nad tablicą z tymi samymi danymi.
  • jeśli zdecydujesz się na iterację nad słownikiem, nie próbuj być zbyt sprytny, chociaż wolniej możesz zrobić o wiele gorzej niż używając standardowej metody foreach.
 30
Author: Liath,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-28 12:22:57

Jest wiele opcji. Mój ulubiony to KeyValuePair

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

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

Możesz również użyć kolekcji kluczy i wartości

 29
Author: theo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-12 10:17:29

Z .NET Framework 4.7 można użyć rozkładu

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

Aby ten kod działał w niższych wersjach C#, dodaj System.ValueTuple NuGet package i napisz gdzieś

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;
    }
}
 16
Author: Pavel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-17 15:18:55

Jak już wspomniano na tej ODPOWIEDŹ, KeyValuePair<TKey, TValue> implementuje a Deconstruct metoda zaczynająca się na. Net Core 2.0,. Net Standard 2.1 i. NET Framework 5.0 (podgląd).

Dzięki temu możliwe jest iterację poprzez słownik w sposóbKeyValuePair agnostyczny:

var dictionary = new Dictionary<int, string>();

// ...

foreach (var (key, value) in dictionary)
{
    // ...
}
 15
Author: rucamzu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-05 01:51:55

Od C # 7 można dekonstruować obiekty na zmienne. Uważam, że jest to najlepszy sposób na iterację słownika.

Przykład:

Utwórz metodę rozszerzenia na KeyValuePair<TKey, TVal>, która ją dekonstruuje:

public static void Deconstruct<TKey, TVal>(this KeyValuePair<TKey, TVal> pair, out TKey key, out TVal value)
{
   key = pair.Key;
   value = pair.Value;
}

Iteruj nad dowolnym Dictionary<TKey, TVal> w następujący sposób

// Dictionary can be of any types, just using 'int' and 'string' as examples.
Dictionary<int, string> dict = new Dictionary<int, string>();

// Deconstructor gets called here.
foreach (var (key, value) in dict)
{
   Console.WriteLine($"{key} : {value}");
}
 14
Author: Domn Werner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-10-03 09:39:00

Zasugerowałeś poniżej iterację

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 nie działa, jeśli wartość jest typu object.

 12
Author: George Stocker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-12 16:01:15

Najprostsza forma do iteracji słownika:

foreach(var item in myDictionary)
{ 
    Console.WriteLine(item.Key);
    Console.WriteLine(item.Value);
}
 11
Author: Ron,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-13 15:35:17

Używając C# 7 , dodaj tę metodę rozszerzenia do dowolnego projektu Twojego rozwiązania:

public static class IDictionaryExtensions
{
    public static IEnumerable<(TKey, TValue)> Tuples<TKey, TValue>(
        this IDictionary<TKey, TValue> dict)
    {
        foreach (KeyValuePair<TKey, TValue> kvp in dict)
            yield return (kvp.Key, kvp.Value);
    }
}


I użyj tej prostej składni

foreach (var(id, value) in dict.Tuples())
{
    // your code using 'id' and 'value'
}


Albo Ten, jeśli wolisz

foreach ((string id, object value) in dict.Tuples())
{
    // your code using 'id' and 'value'
}


W miejsce tradycyjnego

foreach (KeyValuePair<string, object> kvp in dict)
{
    string id = kvp.Key;
    object value = kvp.Value;

    // your code using 'id' and 'value'
}


Metoda rozszerzenia przekształca {[4] } twojego IDictionary<TKey, TValue> w silnie wpisaną tuple, co pozwala na użycie nowej wygodnej składni.

Konwertuje - tylko-wymagane wpisy słownikowe do tuples, więc nie konwertuje całego słownika na tuples, więc nie ma z tym żadnych problemów związanych z wydajnością.

Istnieje tylko niewielki koszt wywołania metody rozszerzenia do tworzenia tuple w porównaniu z bezpośrednim użyciem KeyValuePair, co nie powinno być problemem, jeśli przypisujesz właściwości KeyValuePair Key i Value do nowych zmiennych pętli.

W praktyce ta nowa składnia bardzo dobrze pasuje do większości przypadków, z wyjątkiem niskiej wydajności ultra-wysokiej scenariusze, w których nadal masz możliwość po prostu nie używać go w danym miejscu.

Zobacz to: blog MSDN-nowe funkcje w C# 7

 10
Author: sɐunıɔןɐqɐp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-01 20:38:35

foreach jest najszybszy i jeśli tylko iterujesz ___.Values, jest również szybszy

Tutaj wpisz opis obrazka

 10
Author: Pixel_95,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-11-26 14:56:43

Wiem, że to bardzo stare pytanie, ale stworzyłem kilka metod rozszerzeń, które mogą być przydatne:

    public static void ForEach<T, U>(this Dictionary<T, U> d, Action<KeyValuePair<T, U>> a)
    {
        foreach (KeyValuePair<T, U> p in d) { a(p); }
    }

    public static void ForEach<T, U>(this Dictionary<T, U>.KeyCollection k, Action<T> a)
    {
        foreach (T t in k) { a(t); }
    }

    public static void ForEach<T, U>(this Dictionary<T, U>.ValueCollection v, Action<U> a)
    {
        foreach (U u in v) { a(u); }
    }

W ten sposób mogę napisać kod w ten sposób:

myDictionary.ForEach(pair => Console.Write($"key: {pair.Key}, value: {pair.Value}"));
myDictionary.Keys.ForEach(key => Console.Write(key););
myDictionary.Values.ForEach(value => Console.Write(value););
 7
Author: boca,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-06-14 18:06:18

Znalazłem tę metodę w dokumentacji dla klasy DictionaryBase na MSDN:

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

To był jedyny, który udało mi się poprawnie funkcjonować w klasie, która odziedziczyła po bazie słownikowej.

 6
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-17 23:51:39

Czasami, jeśli potrzebujesz tylko wartości do wyliczenia, użyj kolekcji wartości słownika:

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

Zgłoszone przez ten post, który stwierdza, że jest to najszybsza Metoda: http://alexpinsker.blogspot.hk/2010/02/c-fastest-way-to-iterate-over.html

 6
Author: ender,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-02 01:55:08

Skorzystam z. NET 4.0+ i podam zaktualizowaną odpowiedź na pierwotnie zaakceptowaną:

foreach(var entry in MyDic)
{
    // do something with entry.Value or entry.Key
}
 3
Author: yazanpro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-01 23:17:52

Standardowy sposób iteracji nad słownikiem, zgodnie z oficjalną dokumentacją MSDN to:

foreach (DictionaryEntry entry in myDictionary)
{
     //Read entry.Key and entry.Value here
}
 3
Author: Nick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-28 10:58:55

Jeśli powiedzmy, chcesz iterować nad kolekcją wartości domyślnie, wierzę, że możesz zaimplementować IEnumerable, gdzie T jest typem obiektu values w słowniku, A "this" jest słownikiem.

public new IEnumerator<T> GetEnumerator()
{
   return this.Values.GetEnumerator();
}
 2
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-09 04:16:11

Napisałem rozszerzenie do loop over a dictionary.

public static class DictionaryExtension
{
    public static void ForEach<T1, T2>(this Dictionary<T1, T2> dictionary, Action<T1, T2> action) {
        foreach(KeyValuePair<T1, T2> keyValue in dictionary) {
            action(keyValue.Key, keyValue.Value);
        }
    }
}

Wtedy możesz zadzwonić

myDictionary.ForEach((x,y) => Console.WriteLine(x + " - " + y));
 2
Author: Steven Delrue,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-08 07:07:02
var dictionary = new Dictionary<string, int>
{
    { "Key", 12 }
};

var aggregateObjectCollection = dictionary.Select(
    entry => new AggregateObject(entry.Key, entry.Value));
 0
Author: Egor Okhterov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-28 15:00:10

Dictionary jest to OGÓLNA Klasa kolekcji w c# i przechowuje dane w formacie wartości klucza.Klucz musi być unikalny i nie może być null natomiast wartość może być duplikowana i null.As każda pozycja w słowniku jest traktowana jako KeyValuePair struktura reprezentująca klucz i jego wartość. i dlatego powinniśmy przyjąć element typu KeyValuePair podczas iteracji elementu.Poniżej znajduje się przykład.

Dictionary<int, string> dict = new Dictionary<int, string>();
dict.Add(1,"One");
dict.Add(2,"Two");
dict.Add(3,"Three");

foreach (KeyValuePair<int, string> item in dict)
{
    Console.WriteLine("Key: {0}, Value: {1}", item.Key, item.Value);
}
 0
Author: Sheo Dayal Singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-16 11:25:37

Mamy wiele różnych sposobów, aby to zrobić nad słownikiem.

Możemy przepętać wszystkie KeyValuePair<K,V> w Słowniku i wydrukować odpowiedni klucz i wartość dla każdej pary. Jest to prosty przykład jednej drogi.

using System;
using System.Collections.Generic;
 
public class Example
{
    public static void PrintDict<K,V>(Dictionary<K,V> dict)
    {
        foreach (KeyValuePair<K,V> entry in dict)
        {
            Console.WriteLine(entry.Key + " : " + entry.Value);
        }
    }
 
    public static void Main()
    {
        Dictionary<string, string> dict = new Dictionary<string, string>
        {
            { "key1", "value1" },
            { "key2", "value2" }
        };
 
        PrintDict(dict);
    }
}
 
/*
    Output:
 
    key1 : value1
    key2 : value2
*/

Możemy również iterować nad kolekcją kluczy i pobrać wartość za pomocą właściwości Item[TKey].

using System;
using System.Collections.Generic;
 
public class Example
{
    public static void PrintDict<K,V>(Dictionary<K,V> dict)
    {
        foreach (K key in dict.Keys)
        {
            Console.WriteLine(key + " : " + dict[key]);
        }
    }
 
    public static void Main()
    {
        Dictionary<string, string> dict = new Dictionary<string, string>
        {
            { "key1", "value1" },
            { "key2", "value2" }
        };
 
        PrintDict(dict);
    }
}
 
/*
    Output:
 
    key1 : value1
    key2 : value2
*/

Począwszy od C# 7.0, wiele pól może być pobranych z obiektu w ramach jednej operacji dekonstrukcji poprzez przypisanie wybranych wartości do poszczególne zmienne. Poniższy przykład wykorzystuje wnioskowanie typu podczas dekonstrukcji wewnątrz pętli foreach, co pozwala nam rozpakować klucz i wartość w KeyValuePair<K,V> w jednej operacji.

using System;
using System.Collections.Generic;
 
public class Example
{
    public static void PrintDict<K,V>(Dictionary<K,V> dict)
    {
        foreach (var (key, value) in dict) {
            Console.WriteLine(key + " : " + value);
        }
    }
 
    public static void Main()
    {
        Dictionary<string, string> dict = new Dictionary<string, string>
        {
            { "key1", "value1" },
            { "key2", "value2" }
        };
 
        PrintDict(dict);
    }
}
 
/*
    Output:
 
    key1 : value1
    key2 : value2
*/

Możemy również jawnie zadeklarować typ każdego pola wewnątrz nawiasów, jak pokazano poniżej.

using System;
using System.Collections.Generic;
 
public class Example
{
    public static void PrintDict<K,V>(Dictionary<K,V> dict)
    {
        foreach ((K key, V value) in dict) {
            Console.WriteLine(key + " : " + value);
        }
    }
 
    public static void Main()
    {
        Dictionary<string, string> dict = new Dictionary<string, string>
        {
            { "key1", "value1" },
            { "key2", "value2" }
        };
 
        PrintDict(dict);
    }
}
 
/*
    Output:
 
    key1 : value1
    key2 : value2
*/

Możemy również użyć pętli for do iteracji nad katalogiem. Aby uzyskać KeyValuePair<K,V> w określonym indeksie w sekwencji, użyj metody ElementAT.

using System;
using System.Linq;
using System.Collections.Generic;
 
public class Example
{
    public static void PrintDict<K,V>(Dictionary<K,V> dict)
    {
        for (int i = 0; i < dict.Count; i++)
        {
            KeyValuePair<K, V> entry = dict.ElementAt(i);
            Console.WriteLine(entry.Key + " : " + entry.Value);
        }
    }
 
    public static void Main()
    {
        Dictionary<string, string> dict = new Dictionary<string, string>
        {
            { "key1", "value1" },
            { "key2", "value2" }
        };
 
        PrintDict(dict);
    }
}
 
/*
    Output:
 
    key1 : value1
    key2 : value2
*/

Proste i dość skuteczne rozwiązanie iteracji w dużych słownikach używa się metody ParallelEnumerable.ForAll. Metoda ta jest zilustrowana poniżej: -

using System;
using System.Linq;
using System.Collections.Generic;
 
public class Example
{
    public static void PrintDict<K,V>(Dictionary<K,V> dict)
    {
        dict.AsParallel()
            .ForAll(entry => Console.WriteLine(entry.Key + " : " + entry.Value));
    }
 
    public static void Main()
    {
        Dictionary<string, string> dict = new Dictionary<string, string>
        {
            { "key1", "value1" },
            { "key2", "value2" }
        };
 
        PrintDict(dict);
    }
}
 
/*
    Output:
 
    key1 : value1
    key2 : value2
*/

Również metoda String.Join może być użyta do wypisania wszystkich KeyValuePair<K,V> w słowniku oddzielonych ogranicznikiem.

using System;
using System.Collections.Generic;
 
public class Example
{
    public static void Main()
    {
        Dictionary<string, string> dict = new Dictionary<string, string>
        {
            { "key1", "value1" },
            { "key2", "value2" }
        };
 
        Console.WriteLine(String.Join(Environment.NewLine, dict));
    }
}
 
/*
    Output:
 
    [key1, value1]
    [key2, value2]
*/

Mam nadzieję, że to wyjaśni wszystkie możliwe różne sposoby iteracji nad słownikiem w C # .

 0
Author: Raksha Saini,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-01-10 06:27:49

Chciałem tylko dodać mój 2 cent, ponieważ większość odpowiedzi dotyczy foreach-loop. Proszę spojrzeć na następujący 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));
});

Altought this adds a additional call of '.ToList ()", może wystąpić niewielka poprawa wydajności (jak wskazano tutaj foreach vs someList.Foreach () {} ), szczególnie podczas pracy z dużymi słownikami i pracy równolegle nie ma opcji / nie będzie miał żadnego efektu.

Należy również pamiętać, że nie będzie można przypisać wartości do właściwość 'Value' wewnątrz pętli foreach. Z drugiej strony, będziesz w stanie manipulować "kluczem", jak również, prawdopodobnie wpakować cię w kłopoty w czasie wykonywania.

Kiedy chcesz po prostu "odczytać" klucze i wartości, możesz również użyć IEnumerable.Select ().

var newProductPrices = myProductPrices.Select(kvp => new { Name = kvp.Key, Price = kvp.Value * 1.15 } );
 -1
Author: Alex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:47

Jeśli chcesz użyć pętli for, możesz to zrobić:

var keyList=new List<string>(dictionary.Keys);
for (int i = 0; i < keyList.Count; i++)
{
   var key= keyList[i];
   var value = dictionary[key];
 }
 -1
Author: Seçkin Durgay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-05-14 12:59:52

Najlepszą odpowiedzią jest oczywiście: nie używaj dokładnego słownika, jeśli planujesz nad nim iterację - o czym wspomniał już Vikas Gupta w dyskusji pod pytaniem. Ale tej dyskusji, jak cały ten wątek, wciąż brakuje zaskakująco dobrych alternatyw. Jeden to:

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

Dlaczego Wiele osób uważa to za zapach kodu iteracji nad słownikiem (np. przez foreach (KeyValuePair): Jest to dość zaskakujące, ale jest trochę przytoczona, ale podstawowa zasada czystości Kodowanie: "wyraź intencję!" Robert C. Martin pisze w "Clean Code": "wybór nazw, które ujawniają intencję". Najwyraźniej jest za słaby. "wyrażać (ujawniać) intencje przy każdej decyzji kodowania " byłoby lepiej. Moje słowa. Brakuje mi dobrego pierwszego źródła, ale jestem pewien, że są... Pokrewną zasadą jest " zasada najmniejszego zaskoczenia" (=zasada najmniejszego zdziwienia ).

Dlaczego jest to związane z iteracją nad słownikiem? Wybór słownika wyraża zamiar wyboru struktury danych, która została wykonana do wyszukiwania danych za pomocą klucza . W dzisiejszych czasach istnieje tak wiele alternatyw w. NET, jeśli chcesz iterację przez pary klucz / wartość, że nie potrzebujesz tej kuli.

Ponadto: jeśli iterujesz nad czymś, musisz ujawnić coś o tym, jak przedmioty są (do) zamawiane i oczekiwane do zamówienia! AFAIK, Słownik nie ma specyfikacji co do porządkowania (tylko konwencje specyficzne dla implementacji). Jakie są alternatywy?

TLDR:
SortedList: jeśli Twoja kolekcja nie jest zbyt duża, prostym rozwiązaniem byłoby użycie SortedList, które daje również pełne indeksowanie par klucz / wartość.

Microsoft ma długi artykuł o wspominaniu i wyjaśnianiu dopasowanych zbiorów:
Kolekcja Keyed

Aby wymienić najważniejsze: KeyedCollection i SortedDictionary. SortedDictionary jest nieco szybszy niż SortedList dla oly wstawianie, jeśli robi się duże, ale nie ma indeksowania i jest potrzebne tylko wtedy, gdy O (log n) do wstawiania jest preferowane niż inne operacje. Jeśli naprawdę potrzebujesz O (1) do wstawiania i akceptowania wolniejszych iteracji w zamian, musisz pozostać przy prostym słowniku. Oczywiście nie ma struktury danych, która jest najszybsza dla każdej możliwej operacji..

Dodatkowo istnieje ImmutableSortedDictionary .

A jeśli jedna struktura danych nie jest dokładnie tym, czego potrzebujesz, to wywołaj z Słownik lub nawet z nowego ConcurrentDictionary i dodaj jawne funkcje iteracji/sortowania!

 -1
Author: Philm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-01-22 16:17:13