Вопрос: Каков наилучший способ перебора словаря?


Я видел несколько разных способов перебора словаря на C #. Есть ли стандартный способ?


1905


источник


Ответы:


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

2827



Если вы пытаетесь использовать общий словарь в C #, как если бы вы использовали ассоциативный массив на другом языке:

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

Или, если вам нужно только перебирать набор ключей, используйте

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

И, наконец, если вас интересуют только значения:

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

(Обратите внимание, что varключевое слово - это дополнительная функция C # 3.0 и выше, вы также можете использовать точный тип своих ключей / значений)


624



В некоторых случаях вам может понадобиться счетчик, который может быть предоставлен путем реализации цикла. Для этого LINQ предоставляет ElementAtкоторый позволяет:

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

104



Зависит от того, находитесь ли вы за клавишами или значениями ...

Из MSDN Dictionary(TKey, TValue)Описание класса:

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

73



Как правило, просить «лучший способ» без конкретного контекста - это спрашивать, какой лучший цвет.

С одной стороны, есть много цветов, и лучшего цвета нет. Это зависит от необходимости и часто от вкуса.

С другой стороны, существует много способов перебора словаря на C #, и нет лучшего способа. Это зависит от необходимости и часто от вкуса.

Самый простой способ

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

Если вам нужно только значение (позволяет вызвать его item, более читаемым, чем kvp.Value).

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

Если вам нужен конкретный порядок сортировки

В общем, новички удивляются порядку перечисления Словаря.

LINQ обеспечивает сжатый синтаксис, который позволяет указать порядок (и многое другое), например:

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

Опять вам понадобится только значение. LINQ также обеспечивает краткое решение:

  • итерация непосредственно по значению (позволяет вызвать его item, более читаемым, чем kvp.Value)
  • но отсортированы по клавишам

Вот:

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

Из этих примеров можно сделать много примеров использования в реальном мире. Если вам не нужен конкретный заказ, просто придерживайтесь «самого простого пути» (см. Выше)!


54



Я бы сказал, что foreach - стандартный способ, хотя он, очевидно, зависит от того, что вы ищете

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

Это то, что вы ищете?


34



You can also try this on big dictionaries for multithreaded processing.

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

25



There are plenty of options. My personal favorite is by KeyValuePair

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

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

You can also use the Keys and Values Collections


21



I appreciate this question has already had a lot of responses but I wanted to throw in a little research.

Iterating over a dictionary can be rather slow when compared with iterating over something like an array. In my tests an iteration over an array took 0.015003 seconds whereas an iteration over a dictionary (with the same number of elements) took 0.0365073 seconds that's 2.4 times as long! Although I have seen much bigger differences. For comparison a List was somewhere in between at 0.00215043 seconds.

However, that is like comparing apples and oranges. My point is that iterating over dictionaries is slow.

Dictionaries are optimised for lookups, so with that in mind I've created two methods. One simply does a foreach, the other iterates the keys then looks up.

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

    return "Normal";
}

This one loads the keys and iterates over them instead (I did also try pulling the keys into a string[] but the difference was negligible.

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

With this example the normal foreach test took 0.0310062 and the keys version took 0.2205441. Loading all the keys and iterating over all the lookups is clearly a LOT slower!

For a final test I've performed my iteration ten times to see if there are any benefits to using the keys here (by this point I was just curious):

Here's the RunTest method if that helps you visualise what's going on.

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

Here the normal foreach run took 0.2820564 seconds (around ten times longer than a single iteration took - as you'd expect). The iteration over the keys took 2.2249449 seconds.

Edited To Add: Reading some of the other answers made me question what would happen if I used Dictionary instead of Dictionary. In this example the array took 0.0120024 seconds, the list 0.0185037 seconds and the dictionary 0.0465093 seconds. It's reasonable to expect that the data type makes a difference on how much slower the dictionary is.

What are my Conclusions?

  • Avoid iterating over a dictionary if you can, they are substantially slower than iterating over an array with the same data in it.
  • If you do choose to iterate over a dictionary don't try to be too clever, although slower you could do a lot worse than using the standard foreach method.

21