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

голоса
1k

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

Задан 26/09/2008 в 19:20
источник пользователем
На других языках...                            


26 ответов

голоса
2k

foreach(KeyValuePair<string, string> entry in myDictionary)
{
    // do something with entry.Value or entry.Key
}
Ответил 26/09/2008 в 19:22
источник пользователем

голоса
616

Если вы пытаетесь использовать общий словарь в 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 и выше функции, вы можете также использовать точный тип ваших ключей / значений здесь)

Ответил 26/09/2008 в 19:22
источник пользователем

голоса
106

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

for (int index = 0; index < dictionary.Count; index++) {
  var item = dictionary.ElementAt(index);
  var itemKey = item.Key;
  var itemValue = item.Value;
}
Ответил 10/03/2011 в 21:44
источник пользователем

голоса
73

Зависит ли вы после ключей или значений, которые вы ...

Из 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);
}
Ответил 26/09/2008 в 19:27
источник пользователем

голоса
54

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

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

С другой стороны, есть много способов, чтобы перебрать словарь в 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)
}

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

Ответил 10/08/2015 в 11:15
источник пользователем

голоса
33

Я бы сказал, Еогеасп является стандартным способом, хотя это, очевидно, зависит от того, что вы ищете

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

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

Ответил 26/09/2008 в 19:22
источник пользователем

голоса
23

Вы также можете попробовать это на больших словарей для многопоточной обработки.

dictionary
.AsParallel()
.ForAll(pair => 
{ 
    // Process pair.Key and pair.Value here
});
Ответил 11/06/2015 в 13:32
источник пользователем

голоса
21

Есть много вариантов. Мой личный фаворит на KeyValuePair

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

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

Вы можете также использовать ключи и значения Коллекции

Ответил 26/09/2008 в 19:22
источник пользователем

голоса
20

Я ценю этот вопрос уже много ответов, но я хотел бросить в небольшом исследовании.

Перебор словаря может быть довольно медленно, когда по сравнению с итерацией что-то вроде массива. В моих тестах итерация по массиву взяла 0.015003 секунд, тогда как итерации над словарем (с тем же числом элементов) заняла 0.0365073 секунд, что это в 2,4 раза дольше! Хотя я видел гораздо больше различий. Для сравнения список был где-то посередине в 0.00215043 секунд.

Тем не менее, это как сравнивать яблоки и апельсины. Суть в том, что итерация словари медленно.

Словари оптимизированы для поисков, так что с учетом этого я создал два метода. Один просто делает Еогеасп, другие перебирают клавиши на потом смотрит вверх.

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

    return "Normal";
}

Это один загружает ключи и итерацию над ними вместо этого (я также попробовать потянув ключи в строку [], но разница была незначительной.

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

В этом примере нормального тест Еогеаспа взял 0.0310062 и версия ключи взяла 0.2205441. Загрузка всех ключей и итерация всех поисков, очевидно, намного медленнее!

Для окончательного теста я выполнял свои итерации в десять раз, чтобы увидеть, есть ли какие-либо преимущества использования ключей здесь (в этот момент я был просто любопытно):

Вот метод RunTest, если это поможет вам визуализировать то, что происходит.

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

Вот нормальный Еогеасп пробег занял 0.2820564 секунд (примерно в десять раз больше, чем за одну итерацию взяли - как и следовало ожидать). Итерация по клавишам взял 2.2249449 секунд.

Отредактированный Добавление: Чтение некоторые другие ответы заставили меня вопрос , что случилось бы , если бы я использовал словарь вместо словаря. В этом примере массив занял 0.0120024 секунд, список 0.0185037 секунд и словарные 0.0465093 секунд. Разумно ожидать , что тип данных имеет значение на сколько медленнее словарь.

Каковы мои выводы ?

  • Избегайте итерацию словаря, если вы можете, они существенно медленнее, чем итерация массива с теми же данными в нем.
  • Если вы хотите перебрать словарь не пытайтесь быть слишком умным, хотя медленнее, вы могли бы сделать намного хуже, чем при использовании стандартного метода Еогеасп.
Ответил 30/07/2014 в 11:54
источник пользователем

голоса
9

Вы предложили ниже итерацию

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не работает , если значение имеет объект типа.

Ответил 28/10/2009 в 21:49
источник пользователем

голоса
7

Простейшая форма для перебора словаря:

foreach(var item in myDictionary)
{ 
    Console.WriteLine(item.Key);
    Console.WriteLine(item.Value);
}
Ответил 02/10/2016 в 04:00
источник пользователем

голоса
6

С .NET Framework 4.7можно использовать разложение

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

Для того, чтобы сделать этот код работать на более низких версиях C #, добавить System.ValueTuple NuGet packageи написать где - нибудь

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;
    }
}
Ответил 17/10/2017 в 15:18
источник пользователем

голоса
6

Иногда, если нужно только значения, которые будут перечислены, используйте коллекцию значение в словаря:

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

Сообщил этот пост в котором говорится , что это самый быстрый способ: http://alexpinsker.blogspot.hk/2010/02/c-fastest-way-to-iterate-over.html

Ответил 02/07/2014 в 02:55
источник пользователем

голоса
5

C # 7.0 введены Deconstructors и если вы используете .NET Core , 2.0+ Заявление, структураKeyValuePair<>уже включаютсебяDeconstruct()для вас. Таквы можете сделать:

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

введите описание изображения здесь

Ответил 07/01/2019 в 20:30
источник пользователем

голоса
5

Я нашел этот метод в документации для класса DictionaryBase на MSDN:

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

Это был единственный один я смог правильно функционировать в классе, который унаследовал от DictionaryBase.

Ответил 18/02/2009 в 00:51
источник пользователем

голоса
3

Стандартный способ перебрать словарь, согласно официальной документации на MSDN является:

foreach (DictionaryEntry entry in myDictionary)
{
     //Read entry.Key and entry.Value here
}
Ответил 28/07/2016 в 10:58
источник пользователем

голоса
3

Я возьму преимущество .NET 4.0+ и представить обновленный ответ на первоначально приняла одно:

foreach(var entry in MyDic)
{
    // do something with entry.Value or entry.Key
}
Ответил 02/10/2014 в 00:17
источник пользователем

голоса
2

По состоянию на C # 7, вы можете разрушить объекты в переменные. Я считаю, что это лучший способ, чтобы перебрать словарь.

Пример:

Создать метод расширения на KeyValuePair<TKey, TVal>который разбирает это:

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

Итерации над любым Dictionary<TKey, TVal>следующим образом

// 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}");
}
Ответил 11/07/2018 в 18:05
источник пользователем

голоса
2

Если скажем, вы хотите перебрать коллекцию значений по умолчанию, я верю, что можно реализовать IEnumerable <>, где T является типом значений объекта в словаре, и «это» есть словарь.

public new IEnumerator<T> GetEnumerator()
{
   return this.Values.GetEnumerator();
}
Ответил 09/12/2008 в 05:16
источник пользователем

голоса
1

Я написал расширение для перебрать словарь.

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

Тогда вы можете позвонить

myDictionary.ForEach((x,y) => Console.WriteLine(x + " - " + y));
Ответил 08/06/2018 в 07:07
источник пользователем

голоса
1

Просто хотел бы добавить мои 2 цента, так как большинство ответов относятся к каждому элементу контура. Пожалуйста, обратите внимание на следующий код:

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 это добавляет дополнительный вызов «.ToList ()», может быть небольшая производительность улучшение (как было указано здесь Еогеасп против someList.Foreach () {} ), espacially при работе с большими словарями и работает параллельно нет опция / не будет иметь эффекта.

Кроме того, обратите внимание, что вы не сможете присвоить значение свойства «Value» внутри Еогеасп петли. С другой стороны, вы будете иметь возможность манипулировать «ключ», а также, возможно получение вас в неприятности во время выполнения.

Когда вы просто хотите «читать» ключи и значения, вы можете также использовать IEnumerable.Select ().

var newProductPrices = myProductPrices.Select(kvp => new { Name = kvp.Key, Price = kvp.Value * 1.15 } );
Ответил 16/09/2016 в 16:03
источник пользователем

голоса
0

в дополнении к высшим постам рейтинга, где есть дискуссия между использованием

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

или же

foreach(var entry in myDictionary)
{
    // do something with entry.Value or entry.Key
}

Наиболее полным является следующее, потому что вы можете увидеть тип словаря от инициализации, КВП является KeyValuePair

var myDictionary = new Dictionary<string, string>(x);//fill dictionary with x

foreach(var kvp in myDictionary)//iterate over dictionary
{
    // do something with kvp.Value or kvp.Key
}
Ответил 19/08/2018 в 20:50
источник пользователем

голоса
0

Учитывая следующий словарь:

Dictionary<string, object> dict = new Dictionary<string, object>() { /* ... */ };


В C # 7.0 , вместо того , чтобы писать код , как это:

foreach (KeyValuePair<string, object> kvp in dict)
{
    string id = kvp.Key;
    object value = kvp.Value;
    // your code using 'id' and 'value'
}


Вы можете просто написать это:

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

Или это:

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

Добавляя следующее расширение для вашего решения:

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

В стоимости создания Tupleдля каждой петли KeyValuePairвместо переменных, первого цикла в.

Ответил 27/05/2018 в 12:25
источник пользователем

голоса
0

Dictionary <TKey, TValue> Это общий класс коллекции в C # и сохраняет данные в значение ключа format.Key должно быть уникальным и не может быть пустым , тогда как значение может быть дубликатом и null.As каждый элемент в словаре рассматривается как KeyValuePair структура <TKey, TValue> , представляющий ключ и его значение. и , следовательно , мы должны взять на себя тип элемента KeyValuePair <TKey, TValue> во время итерации элемента. Ниже приведен пример.

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);
}
Ответил 16/04/2018 в 11:25
источник пользователем

голоса
-1

Словари специальные списки, в то время как каждое значение в списке есть ключ, который также является переменным. Хорошим примером словаря является телефонная книга.

   Dictionary<string, long> phonebook = new Dictionary<string, long>();
    phonebook.Add("Alex", 4154346543);
    phonebook["Jessica"] = 4159484588;

Обратите внимание на то, что при определении словаря, мы должны дать общее определение двух типов - тип ключа и тип значения. В этом случае ключ является строкой, в то время как значение является целым числом.

Есть также два способа добавления одного значения в словаре, либо с помощью оператора скобки или с помощью метода Add.

Для того, чтобы проверить, есть ли словарь определенный ключ в нем, мы можем использовать метод ContainsKey:

Dictionary<string, long> phonebook = new Dictionary<string, long>();
phonebook.Add("Alex", 415434543);
phonebook["Jessica"] = 415984588;

if (phonebook.ContainsKey("Alex"))
{
    Console.WriteLine("Alex's number is " + phonebook["Alex"]);
}

Чтобы удалить элемент из словаря, мы можем использовать метод Remove. Удаление элемента из словаря по его ключу быстро и очень эффективно. При удалении элемента из списка, используя его значение, процесс идет медленно и неэффективно, в отличие от функции словаря Удалить.

Dictionary<string, long> phonebook = new Dictionary<string, long>();
phonebook.Add("Alex", 415434543);
phonebook["Jessica"] = 415984588;

phonebook.Remove("Jessica");
Console.WriteLine(phonebook.Count);
Ответил 09/03/2018 в 06:02
источник пользователем

голоса
-1
var dictionary = new Dictionary<string, int>
{
    { "Key", 12 }
};

var aggregateObjectCollection = dictionary.Select(
    entry => new AggregateObject(entry.Key, entry.Value));
Ответил 28/05/2015 в 15:00
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more