25 ответов:
foreach(KeyValuePair<string, string> entry in myDictionary) { // do something with entry.Value or entry.Key }
если вы пытаетесь использовать общий словарь в 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 и выше, вы также можете использовать точный тип ключей/значений)
в некоторых случаях вам может понадобиться счетчик, который может быть предоставлен реализацией for-loop. Для этого, LINQ предоставляет
ElementAtчто включает следующее:for (int index = 0; index < dictionary.Count; index++) { var item = dictionary.ElementAt(index); var itemKey = item.Key; var itemValue = item.Value; }
зависит от того, ищете ли вы ключи или значения...
от 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); }
как правило, просить "лучший способ" без определенного контекста-это как спрашивать, какой цвет лучше.
С одной стороны, есть много цветов и нет лучшего цвета. Это зависит от потребности и часто от вкуса, тоже.
С другой стороны, есть много способов перебора словаря в 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) }есть еще много реальных вариантов использования, которые вы можете сделать из этих примеров. Если вам не нужен конкретный заказ, просто придерживайтесь "самого простого способа" (см. выше)!
Я бы сказал, что foreach-это стандартный способ, хотя это, очевидно, зависит от того, что вы ищете
foreach(var kvp in my_dictionary) { ... }Это то, что вы ищете?
вы также можете попробовать это на больших словарей для многопоточной обработки.
dictionary .AsParallel() .ForAll(pair => { // Process pair.Key and pair.Value here });
есть много вариантов. Мой личный фаворит-KeyValuePair
Dictionary<string, object> myDictionary = new Dictionary<string, object>(); // Populate your dictionary here foreach (KeyValuePair<string,object> kvp in myDictionary) { // Do some interesting things }вы также можете использовать коллекции ключей и значений
Я ценю этот вопрос уже было много ответов, но я хотел бросить в небольшое исследование.
итерация по словарю может быть довольно медленной по сравнению с итерацией по чему-то вроде массива. В моих тестах итерация по массиву заняла 0,015003 секунды, тогда как итерация по словарю (с тем же количеством элементов) заняла 0,0365073 секунды, что в 2,4 раза больше! Хотя я видел гораздо большие различия. Для сравнения список был где-то между ними в 0.00215043 секунды.
однако, это похоже на сравнение яблок и апельсинов. Я хочу сказать, что итерация по словарям происходит медленно.
словари оптимизированы для поиска, поэтому с учетом этого я создал два метода. Один просто делает foreach, другой повторяет ключи, а затем смотрит вверх.
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"; }в этом примере обычный тест foreach занял 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); }здесь обычный запуск foreach занял 0,2820564 секунды (примерно в десять раз больше, чем одна итерация, как и следовало ожидать). Итерация по клавишам заняла 2.2249449 секунд.
Редактировать, Чтобы Добавить: Чтение некоторых других ответов заставило меня задаться вопросом, Что произойдет, если я использую словарь вместо словаря. В этом примере массив занял 0,0120024 секунды, список 0,0185037 секунды и словарь 0,0465093 секунды. Разумно ожидать, что тип данных имеет значение, насколько медленнее словарь.
Каковы мои выводы?
- избегайте итерации по словарю, если вы можете, они значительно медленнее, чем итерация по массиву с теми же данными в нем.
- если вы решите перебирать словарь, не пытайтесь быть слишком умным, хотя медленнее вы можете сделать намного хуже, чем с помощью стандартного метода foreach.
вы предложили ниже повторить
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не работает, если значение имеет тип object.
С
.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; } }
самая простая форма для итерации словаря:
foreach(var item in myDictionary) { Console.WriteLine(item.Key); Console.WriteLine(item.Value); }
иногда, если вам нужно только перечислить значения, используйте коллекцию значений словаря:
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
Я нашел этот метод в документации для класса DictionaryBase на MSDN:
foreach (DictionaryEntry de in myDictionary) { //Do some stuff with de.Value or de.Key }Это был единственный, который я смог получить правильно функционирующий в классе, унаследованном от DictionaryBase.
используя C# 7 добавьте метод расширения к любому проекту вашего решения:
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); } }
И используйте этот простой синтаксисforeach (var(id, value) in dict.Tuples()) { // your code using 'id' and 'value' }
Или, если вы предпочитаетеforeach ((string id, object value) in dict.Tuples()) { // your code using 'id' and 'value' }
Вместо традиционногоforeach (KeyValuePair<string, object> kvp in dict) { string id = kvp.Key; object value = kvp.Value; // your code using 'id' and 'value' }
Метод расширения преобразуетKeyValuePairвашегоIDictionary<TKey, TValue>в строго типизированныхtuple, что позволяет использовать этот новый комфортабельный синтаксис.он преобразует - просто-необходимые словарные статьи в
tuples, поэтому он не преобразует весь словарьtuples, так что нет никаких проблем с производительностью, связанных с этим.существует только незначительная стоимость вызова метода расширения для создания
tupleпо сравнению с использованиемKeyValuePairнапрямую, что не должно быть проблемой, если вы не назначаяKeyValuePairсвойстваKeyиValueк новым переменным цикла в любом случае.на практике этот новый синтаксис очень хорошо подходит для большинства случаев, за исключением низкоуровневых сценариев сверхвысокой производительности, где у вас все еще есть возможность просто не использовать его в этом конкретном месте.
зацени вот это: блог MSDN-новые возможности в C# 7
Я воспользуюсь преимуществами .NET 4.0+ и предоставлю обновленный ответ на первоначально принятый:
foreach(var entry in MyDic) { // do something with entry.Value or entry.Key }
стандартный способ перебора словаря, согласно официальной документации по MSDN:
foreach (DictionaryEntry entry in myDictionary) { //Read entry.Key and entry.Value here }
если, скажем, вы хотите перебирать коллекцию values по умолчанию, я считаю, что вы можете реализовать IEnumerable, где T-тип объекта values в словаре, а "это" - словарь.
public new IEnumerator<T> GetEnumerator() { return this.Values.GetEnumerator(); }
начиная с 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}"); }
var dictionary = new Dictionary<string, int> { { "Key", 12 } }; var aggregateObjectCollection = dictionary.Select( entry => new AggregateObject(entry.Key, entry.Value));
просто хотел добавить мой 2 цента, так как большинство ответов относятся к foreach-loop. Пожалуйста, взгляните на следующий код:
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 ()', может быть небольшое улучшение производительности (как указано здесь foreach против someList.Foreach () {}), особенно при работе с большими словарями и параллельной работе нет возможности / не будет иметь никакого эффекта вообще.
кроме того, обратите внимание, что вы не будете возможность присваивать значения свойству "Value" внутри цикла foreach. С другой стороны, вы также сможете манипулировать "ключом", возможно, попадая в неприятности во время выполнения.
когда вы просто хотите "читать" ключи и значения, вы также можете использовать IEnumerable.Выбирать.)(
var newProductPrices = myProductPrices.Select(kvp => new { Name = kvp.Key, Price = kvp.Value * 1.15 } );
Я написал расширение для перебора словарь.
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));
Словарь - это обобщенный класс коллекции в C# и он хранит данные в формате ключ-значение.Ключ должен быть уникальным и не может быть нулевым, тогда как значение может быть дублированным и null.As каждый элемент в словаре рассматривается как структура KeyValuePair, представляющая ключ и его значение. и поэтому мы должны взять тип элемента KeyValuePair во время итерации элемента.Ниже приведен пример.
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); }
В дополнение к самым высоким рейтинговым постам, где есть обсуждение между использованием
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 }наиболее полным является следующее, потому что вы можете увидеть тип словаря от инициализации, kvp является 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 }
словари-это специальные списки, тогда как каждое значение в списке имеет ключ что также является переменной. Хорошим примером словаря является телефонная книга.
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);
Comments