質問
C#で辞書を反復処理するいくつかの異なる方法を見てきました。標準的な方法はありますか?
解決
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ループの実装によって提供されるカウンタが必要になる場合があります。そのために、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);
}
一般的に、<!> quot;最良の方法<!> quot;特定のコンテキストなしで尋ねるようなものです 最高の色は何ですか?
一方で、多くの色があり、最良の色はありません。それは必要性に依存し、しばしば味にも依存します。
一方、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は、以下に対する簡潔なソリューションも提供します
- 値を直接繰り返します(<=>を呼び出すことができ、<=>より読みやすい)
- ただしキーでソート
ここにあります:
foreach (var item in items.OrderBy(kvp => kvp.Key).Select(kvp => kvp.Value))
{
doStuff(item)
}
これらの例から実行できる実世界のユースケースは他にもたくさんあります。 特定の順序が不要な場合は、<!> quot;最も簡単な方法<!> quot; (上記参照)!
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秒の間にありました。
ただし、これはリンゴとオレンジを比較するようなものです。私のポイントは、辞書の繰り返しが遅いということです。
辞書は検索用に最適化されています。そのため、2つのメソッドを作成しました。 1つは単純にforeachを実行し、もう1つはキーを反復して検索します。
public static string Normal(Dictionary<string, string> dictionary)
{
string value;
int count = 0;
foreach (var kvp in dictionary)
{
value = kvp.Value;
count++;
}
return "Normal";
}
これはキーをロードし、代わりに繰り返し処理を行います(キーをstring []にプルしようとしましたが、違いは無視できました。
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がかかりました。すべてのキーをロードし、すべてのルックアップを反復処理することは明らかに遅いです!
最終テストでは、ここでキーを使用することの利点があるかどうかを確認するために10回反復を実行しました(この時点までに興味がありました):
何が起こっているかを視覚化するのに役立つ場合、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秒かかりました(予想どおり、1回の反復にかかった時間の約10倍)。キーの繰り返しには2.2249449秒かかりました。
追加して編集: 他の回答のいくつかを読んで、Dictionaryの代わりにDictionaryを使用するとどうなるか疑問に思いました。この例では、配列は0.0120024秒、リストは0.0185037秒、辞書は0.0465093秒かかりました。データ型によって、辞書の速度がどれだけ遅くなるかを予測するのは理にかなっています。
結論は何ですか?
- 可能な場合は辞書の反復を避け、同じデータを含む配列の反復よりも大幅に遅くなります。
- 辞書を反復処理することを選択した場合、あまり賢くならないようにしてください。ただし、標準のforeachメソッドを使用するよりも遅くなる可能性があります。
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}");
}
反復するために以下を提案しました
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
値がオブジェクト型の場合、<=>は機能しません。
.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);
}
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
に-just-変換するため、ディクショナリ全体がKey
に変換されないため、それに関連するパフォーマンスの懸念はありません。
Value
を直接使用する場合と比較して、<=>を作成するための拡張メソッドを呼び出すだけのわずかなコストがあります。これは、<=>のプロパティ<=>を割り当て、 <=>とにかく新しいループ変数に。
実際には、この新しい構文はほとんどの場合に非常に適しています。ただし、特定の場所で単純に使用しないオプションがある低レベルの超高性能シナリオを除きます。
こちらをご覧ください: MSDNブログ-C#7の新機能
値の列挙のみが必要な場合は、辞書の値コレクションを使用してください:
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
MSDNのDictionaryBaseクラスのドキュメントでこのメソッドを見つけました:
foreach (DictionaryEntry de in myDictionary)
{
//Do some stuff with de.Value or de.Key
}
これは、DictionaryBaseから継承したクラスで正しく機能することができた唯一のものでした。
.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
}
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}");
}
デフォルトで値コレクションを反復処理する場合、IEnumerable <!> lt; <!> gt;を実装できると思います。ここで、Tは辞書の値オブジェクトのタイプで、<! > quot; this <!> quot;辞書です。
public new IEnumerator<T> GetEnumerator()
{
return this.Values.GetEnumerator();
}
var dictionary = new Dictionary<string, int>
{
{ "Key", 12 }
};
var aggregateObjectCollection = dictionary.Select(
entry => new AggregateObject(entry.Key, entry.Value));
ほとんどの回答はforeachループに関連しているため、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));
});
これにより、「。ToList()」の追加呼び出しが追加されるため、わずかなパフォーマンスの改善が行われる場合があります(ここで指摘されているように、 foreach vs someList.Foreach(){} )、 特に大規模な辞書を使用して並行して実行する場合、オプションはありません/まったく効果がありません。
また、foreachループ内の 'Value'プロパティに値を割り当てることができないことに注意してください。一方、「キー」も操作できるため、実行時に問題が発生する可能性があります。
<!> quot; read <!> quot;だけが必要な場合キーと値、IEnumerable.Select()も使用できます。
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));
これは非常に古い質問であることは知っていますが、便利な拡張メソッドをいくつか作成しました。
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); }
}
これにより、次のようなコードを記述できます。
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););
辞書<!> lt; TKey、<!>#8194; TValue <!> gt; これはc#の汎用コレクションクラスであり、データをキー値形式で格納します。ディクショナリの各アイテムはKeyValuePair <!> ltとして扱われるため、重複してnullである必要があります。 TKey、<!>#8194; TValue <!> gt;キーとその値を表す構造。したがって、KeyValuePair <!> lt;という要素タイプを使用する必要があります。 TKey、<!>#8194; TValue <!> gt;要素の反復中。以下が例です。
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;
ディクショナリを定義するとき、ジェネリックを提供する必要があることに注意してください キーのタイプと値のタイプの2つのタイプの定義。この場合、キーは文字列ですが、値は整数です。
大括弧演算子を使用するか、Addメソッドを使用して、辞書に単一の値を追加する2つの方法もあります。
辞書に特定のキーが含まれているかどうかを確認するには、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);