辞書を反復する最良の方法は何ですか?


2627

C#で辞書を反復処理するいくつかの異なる方法を見てきました。標準的な方法はありますか?


108
この質問に対する回答がたくさんあり、1回の923回の投票があったことに驚いています。(foreachコースを使用しています)。少なくとも、辞書を反復する必要がある場合は、私がこのコメントをしなければならなかった。私はこのコメントをしなければならなかった。私は辞書がIMHOが適切でない方法で悪用されているのを見たからだ…そうだ。それはのために設計されています。辞書を反復する方法を不思議に思う前に、それを覚えておいてください。
Vikas Gupta 2014

74
@VikasGuptaキーがどうなるかわからないときに、キーと値のペアのコレクションで何かをするために何を提案しますか?
ナッシュ2015

26
@displayName各キーと値のペアで何かを実行したいが、値の検索に使用するキーへの参照がない場合は、辞書を反復処理しますよね?これはたいてい間違った使い方であるというVikasの主張にもかかわらず、あなたがそれをしたい場合があるかもしれないことをちょうど指摘していました。
nasch 2015年

34
使い方が間違っているというのは、もっと良い方法があるということです。その代わりは何ですか?
カイルデラニー

40
VikasGuptaは間違っています。非理論的なシナリオにおける長年の高性能C#およびC ++プログラミングの後、私は断言できます。実際に、辞書を作成し、一意のキーと値のペアを格納し、これらの値を反復するケースが頻繁にあります。これらの値は、コレクション内に一意のキーがあることが証明されています。追加のコレクションを作成することは、辞書の反復を回避するための非常に非効率的でコストのかかる方法です。あなたの見解を明確にする質問への回答として良い選択肢を提供してください。そうでなければ、あなたのコメントはかなり無意味です。
sɐunıɔןɐqɐp

回答:


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

29
辞書のキー/値のタイプが正確にわからない場合はどうなりますか?var entryその場合は使用する方が良いので、上の答えの代わりに、この答えを再確認して投票ました。
Ozair Kafray、2016年

93
varタイプがわからないときに@OzairKafrayを使用することは、一般的に悪い習慣です。
ネイト

52
Pabloは、戻り値の型を難読化するレイジーコーダーの "var"の使用をデフォルトに設定しなかったため、この答えは優れています。
MonkeyWrench 2016年

119
@MonkeyWrench:まあ。Visual Studioはタイプを認識しています。必要なのは、変数にカーソルを合わせるだけです。
Robert Harvey

31
私が理解してvarいるように、型がコンパイル時にわかっている場合にのみ機能します。Visual Studioがタイプを認識している場合は、それを調べることもできます。
カイルデラニー

866

別の言語で連想配列を使用するような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以上の機能であり、ここではキー/値の正確なタイプを使用することもできます)


11
var機能は、最初のコードブロックに最も必要です:)
nawfal

27
この回答は、キーまたは値を明示的に反復できることを示していることを感謝します。
Rotsiser Mho 2015年

11
ここではvarの使用が好きではありません。それが単に構文上の砂糖であることを考えると、なぜここでそれを使うのですか?誰かがコードを読み取ろうとすると、コードの種類を特定するためにジャンプする必要がありますmyDictionary(もちろん、実際の名前でない限り)。タイプが明らかな場合などは、varを使用するのが適切だと思いますvar x = "some string"が、すぐに明らかでない場合は、コードリーダー/レビューアーを傷つけるのは遅延コーディングだと思います
James Wierzba

8
var私の意見では、控えめに使用する必要があります。特にここでは、それは建設的ではありません。タイプKeyValuePairはおそらく質問に関連しています。
シンジャイ

3
var独特の目的があり、それが「構文的」な砂糖だとは信じていません。それを意図的に使用することは適切なアプローチです。
Joshua K

159

場合によっては、forループの実装によって提供されるカウンターが必要になることがあります。そのために、LINQはElementAt以下を可能にするものを提供します。

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

21
'.ElementAt'メソッドを使用するには、次の点に注意してください。using System.Linq; これはfxには含まれていません。自動生成されたテストクラス。
Tinia

14
これは、キーに関連付けられた値を変更する場合の方法です。そうでない場合、foreach()を変更して使用すると例外がスローされます。
Mike de Klerk 2013

27
ElementAtO(n)操作ではありませんか?
Arturo

162
この回答は、非常に多くの賛成投票に値するものではありません。辞書には暗黙の順序がないため、.ElementAtこのコンテキストで使用すると微妙なバグが発生する可能性があります。はるかに深刻なのは、上記のArturoのポイントです。dictionary.Count + 1O(n)のみであるはずの操作に対して、O(n ^ 2)の複雑さにつながる辞書時間を反復します。インデックスが本当に必要な場合(必要な場合は、最初に間違ったコレクション型を使用している可能性があります)、dictionary.Select( (kvp, idx) => new {Index = idx, kvp.Key, kvp.Value})代わりに反復し.ElementAt、ループ内では使用しないでください。
2015年

5
ElementAt-o(n)操作!マジ?これはあなたがそれをしてはいけない方法の例です。これらの多くの賛成票?
Mukesh Adhvaryu、2016年

96

キーと値のどちらを使用するかによって異なります...

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

82

一般に、特定のコンテキストなしで「最良の方法」を求めることは、何が最良の色であるかを尋ねるような ものです。

一方で、色はたくさんあり、最高の色はありません。それは必要性に依存し、しばしば味にも依存します。

一方、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)
}

これらの例から実行できる、より多くの実際の使用例があります。特定の注文が必要ない場合は、「最も簡単な方法」(上記を参照)を使用してください。


最後.Valuesはselect句ではなく、すべきです。
マフィイ2016

@マフィアよろしいですか?OrderByによって返される値はKeyValuePairタイプではなく、Valueフィールドがありません。私がここで見る正確なタイプはIOrderedEnumerable<KeyValuePair<TKey, TValue>>です。多分あなたは何か他のものを意味しましたか?あなたが意味することを示す完全な行を書くことができますか(そしてそれをテストしてください)?
ステフェイン・グーリッホン

:私はこの答えは私が何を意味するか含まれていると思いますstackoverflow.com/a/141105/5962841を私が何か混乱なら、私を修正
Mafii

1
@Mafii答え全体をもう一度読んでください。コードセクション間の説明でコンテキストがわかります。あなたが言及する答えは私の答えの2番目のコードセクションのようなものです(順序は必要ありません)。そこでitems.Valueあなたが提案したように私は書きました。コメントした4番目のセクションの場合、これSelect()は、foreachキーと値のペアではなく、ディクショナリの値を直接列挙する方法です。Select()この場合、どうしてもが気に入らない場合は、3番目のコードセクションを使用することをお勧めします。4番目のセクションの要点は、コレクションをLINQで前処理できることを示すことです。
ステフェイン・グーリッホン

1
そうする場合は.Keys.Orderby()、キーのリストを反復処理します。それで十分なら、結構です。値が必要な場合は、ループで各キーの辞書をクエリして値を取得する必要があります。多くのシナリオでは、実際的な違いはありません。高性能のシナリオでは、そうなります。答えの冒頭で書いたように、「多くの方法があり(...)、最善の方法はありません。それは、ニーズにも依存し、好みにも依存します。」
ステフェイン・グーリッホン

53

foreachが標準的な方法だと思いますが、それは明らかにあなたが探しているものに依存します

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

それはあなたが探しているものですか?


42
ええと、アイテムに「値」という名前を付けるのは、やや混乱しませんか?通常、 "value.Key"や "value.Value"などの構文を使用します。これは、特に.Net辞書の実装方法に精通していない場合、コードを読む他の人にとって直感的ではありません。 。
RenniePet 14年

3
@RenniePet kvpは、辞書や関連データ構造を反復するときにKeyValuePairインスタンスに名前を付けるために一般的に使用されますforeach(var kvp in myDictionary){...
mbx 2016年

37

マルチスレッド処理用の大きな辞書でこれを試すこともできます。

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

8
@WiiMaxxおよびこれらのアイテムが相互に依存しない場合はより重要
マフィイ

36

C#7.0Deconstructors導入しました。.NETCore 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}");
}

ここに画像の説明を入力してください


5
あなたは4.7.2件まで少なくともKeyValuePairに解体を持っていないの.NET Frameworkを使用している場合、これを試してください:foreach (var (key, value) in dic.Select(x => (x.Key, x.Value)))
nwsmith

29

この質問にはすでに多くの回答があったことを感謝しますが、少し調査を行いたかったのです。

ディクショナリの反復は、配列のようなものの反復と比較すると、かなり遅くなる可能性があります。私のテストでは、配列の反復には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秒かかりました。

追加のために編集: 他の回答のいくつかを読んで、辞書ではなく辞書を使用した場合どうなるか疑問に思いました。この例では、配列は0.0120024秒、リストは0.0185037秒、辞書は0.0465093秒かかりました。データ型によって、ディクショナリの速度がどれほど遅くなるかを予測できるのは当然です。

私の結論は何ですか?

  • 可能であればディクショナリの反復を避けてください。同じデータが含まれている配列を反復するよりもかなり遅くなります。
  • 辞書を反復処理することを選択した場合は、あまり賢くしないでください。遅いとはいえ、標準のforeachメソッドを使用するよりもずっと悪い結果になる可能性があります。

11
あなたは代わりのDateTimeのストップウォッチのようなもので測定する必要があります:hanselman.com/blog/...
でもミエン

2
テストシナリオ、辞書にある項目の数、平均時間を計算するためにシナリオを実行した頻度を教えてください...
WiiMaxx

3
興味深いことに、ディクショナリにどのようなデータがあるかによって、異なる結果が得られます。ディクショナリを反復処理している間、列挙子関数はディクショナリの多くの空のスロットをスキップする必要があるため、配列を反復処理するよりも遅くなります。辞書がいっぱいになると、半分空の場合よりもスキップする空のスロットが少なくなります。
マーティンブラウン

26

たくさんのオプションがあります。私の個人的なお気に入りはKeyValuePairです

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

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

キーと値のコレクションを使用することもできます


14

では.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;
    }
}

9
これは誤りです。.NET 4.7は単にValueTuple組み込まれています。以前のバージョンのnugetパッケージとして使用できます。さらに重要なことに、Deconstructメソッドがのデコンストラクタとして機能するには、C#7.0以降が必要ですvar (fruit, number) in fruits
David Arno

13

C#7以降、オブジェクトを変数に分解できます。これは、辞書を反復処理するための最良の方法だと思います。

例:

KeyValuePair<TKey, TVal>それを分解する拡張メソッドを作成します。

public static void Deconstruct<TKey, TVal>(this KeyValuePair<TKey, TVal> pair, out TKey key, out TVal value)
{
   key = pair.Key;
   value = 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}");
}

10

以下を反復することを提案しました

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

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

参考までにforeach、値がオブジェクト型の場合は機能しません。


4
詳しく説明してください:どの値がタイプである場合はforeach機能しませんか?そうでなければ、これはあまり意味がありません。object
Marc

9

辞書を反復する最も簡単な形式:

foreach(var item in myDictionary)
{ 
    Console.WriteLine(item.Key);
    Console.WriteLine(item.Value);
}

9

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'
}


拡張メソッドはのKeyValuePairIDictionary<TKey, TValue>強く型付けされたに変換し、tupleこの新しい快適な構文を使用できるようにします。

必要なディクショナリエントリだけをtuplesに変換するためtuples、ディクショナリ全体はに変換されないため、これに関連するパフォーマンスの問題はありません。

tupleを使用する場合と比較して、を作成するための拡張メソッドの呼び出しにはわずかなコストしかかかりKeyValuePairません。これは、KeyValuePairのプロパティKeyValue新しいループ変数を割り当てている場合は問題になりません。

実際には、この新しい構文はほとんどの場合に非常に適しています。ただし、特定の場所でそれを使用しないオプションがまだある低レベルの超高パフォーマンスシナリオは除きます。

これをチェックしてください:MSDNブログ-C#7の新機能


1
キーと値のペアよりも「快適な」タプルを選ぶ理由は何でしょうか?ここには利益がありません。タプルにはキーと値が含まれているため、キーと値のペアも含まれています。
Maarten、

4
こんにちはマーティン、ご質問ありがとうございます。主な利点は、追加のプログラミング作業なしのコードの読みやすさです。KeyValuePairでは、常にフォームkvp.Keyを使用し、kvp.Valueキーと値をそれぞれ使用する必要があります。タプルを使用すると、foreachブロック内でさらに変数宣言を使用することなく、キーと値に自由に名前を付けることができます。たとえば、キーにfactoryName、値にと名前を付けることができますmodels。これは、ネストされたループ(辞書の辞書)を取得するときに特に役立ちます。コードのメンテナンスがはるかに簡単になります。ぜひお試しください!;-)
sɐunıɔןɐqɐp

7

私はこれが非常に古い質問であることを知っていますが、役に立つかもしれないいくつかの拡張メソッドを作成しました:

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

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


パフォーマンスを向上させるための+1。実際、ディクショナリ自体の反復には、必要なものがすべて値である場合、オーバーヘッドが含まれます。これは主に、KeyValuePair構造体に値または参照をコピーするためです。
Jaanus Varus

1
そのリンクの最後のテストは、間違ったテストです。前の2つのテストは値を使用しますが、キーの反復を測定して値を無視します。
Crescent Fresh

5

このメソッドは、MSDNのDictionaryBaseクラスのドキュメントで見つかりました。

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

これは、DictionaryBaseから継承したクラスで正しく機能する唯一のものでした。


3
これは、ジェネリックでないバージョンのディクショナリを使用しているときのようです。つまり、.NET Framework 2.0より前のバージョンです。
joedotnot 14

@ joed0tnot:それがために使用される非ジェネリック版であるHashtableオブジェクト
sɐunıɔןɐqɐp

5

foreachが最も速く、反復するだけの場合___.Valuesは、それよりも速くなります

ここに画像の説明を入力してください


なぜあなたは、呼び出しているContainsKey()forバージョン?これにより、比較対象のコードにはないオーバーヘッドが追加されます。TryGetValue()「キーが存在する場合、アイテムをキーで取得する」パターンを置き換えるために存在します。さらに、dictから0までの連続した整数の範囲が含まれている場合dictCount - 1、インデクサーは失敗しないことがわかります。それ以外の場合は、dict.Keys反復する必要があります。どちらの方法でも、ContainsKey()/はTryGetValue()必要ありません。最後に、コードのスクリーンショットを投稿しないでください。
BACON

3

私は.NET 4.0+を利用して、最初に受け入れられたものに対する更新された回答を提供します。

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

3

MSDNの公式ドキュメントによると、辞書を反復する標準的な方法は次のとおりです。

foreach (DictionaryEntry entry in myDictionary)
{
     //Read entry.Key and entry.Value here
}

2

辞書をループする拡張機能を作成しました。

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

あなたForEachが持っているメソッドを定義しましたforeach (...) { }...不要のようです。
Maarten

1

たとえば、デフォルトで値コレクションを反復処理したい場合、IEnumerable <>を実装できると思います。Tはディクショナリ内の値オブジェクトのタイプで、「this」はディクショナリです。

public new IEnumerator<T> GetEnumerator()
{
   return this.Values.GetEnumerator();
}

1

ほとんどの答えは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とsomeList.Foreach(){}で指摘されているように、パフォーマンスが若干向上する可能性があります。オプション/はまったく効果がありません。

また、foreachループ内の「Value」プロパティに値を割り当てることができないことに注意してください。一方、「キー」も操作できるため、実行時に問題が発生する可能性があります。

キーと値を「読み取る」だけの場合は、IEnumerable.Select()を使用することもできます。

var newProductPrices = myProductPrices.Select(kvp => new { Name = kvp.Key, Price = kvp.Value * 1.15 } );

5
理由もなくコレクション全体をコピーしても、パフォーマンス向上しません。コードの速度が劇的に低下し、追加のメモリをほとんど消費しないはずのコードのメモリフットプリントが2倍になります。
サービー

副作用の「List.ForEach」メソッドを避けforeachます。副作用の可視性を強制します。
user2864740 2017年

0
var dictionary = new Dictionary<string, int>
{
    { "Key", 12 }
};

var aggregateObjectCollection = dictionary.Select(
    entry => new AggregateObject(entry.Key, entry.Value));

2
この回答には、より正当化/説明が必要です。何をAggregateObject追加しKeyValuePairますか?質問で要求されている「反復」はどこにありますか?
Marc L.17年

Selectはディクショナリを反復処理し、各オブジェクトを操作できるようにします。ほど一般的ではありませんforeachが、私は何度も使用しています。私の回答は本当に反対票に値しましたか?
ピクサー

いいえ、反復をSelect 使用して結果に影響を与えますが、それ自体はイテレーターではありません。反復(foreach)が使用されるもののタイプ(特に副作用のある操作)は、Linqの範囲外Selectです。ラムダaggregateObjectCollectionは、実際に列挙されるまで実行されません。この回答を「最初のパス」(つまり、ストレートの前に使用foreach)とすると、悪い習慣が助長されます。状況によっては、ディクショナリを反復する前に役立つLinq操作があるかもしれませんが、これは要求された質問には対応していません。
Marc L.

0

Dictionary <TKey、TValue>これはc#のジェネリックコレクションクラスであり、データをキー値形式で格納します。キーは一意である必要があり、nullにすることはできませんが、値は重複してnullにすることができます。ディクショナリ内の各アイテムはキーとその値を表す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);
}

0

forループを使用したい場合、これを行うことができます:

var keyList=new List<string>(dictionary.Keys);
for (int i = 0; i < keyList.Count; i++)
{
   var key= keyList[i];
   var value = dictionary[key];
 }

しかし、これの利点は何ですか?これは、より長いコードだforeachループ ために悪いパフォーマンスをnew List<string>(dictionary.Keys)繰り返すだろうdictionary.Count、あなたもそれを自分で反復する機会を持つ前に、時間を。「最善の方法」を求めることは主観的であることはさておき、質問が求める「最善の方法」または「標準的な方法」のどちらにこれが当てはまるかはわかりません。「forループを使用したい場合...」には、「ループを使用しない」と対抗しforます。
BACON

大規模なコレクションがあり、foreachの操作が遅い場合、および反復時にコレクションを変更できる場合、「コレクションが変更されました」エラーから保護され、このソリューションはElementAtを使用するよりもパフォーマンスが向上します。
SeçkinDurgay

「コレクションが変更されました」の例外を回避することがこれを行う1つの理由であることに同意しますが、その特別なケースは質問には記載されておらず、いつでも行うことができますforeach (var pair in dictionary.ToArray()) { }。それでも、このコードを使用する特定のシナリオと、その使用の影響を回答で明確にするとよいと思います。
BACON

はい、あなたは正しいですが、そこに答えはElementAtにここにあり、それは非常に高い評価を得ていると私はこの答え:)入った
SeçkinDurgayを

0

この回答ですでに指摘したよう、.NET Core 2.0、.NET Standard 2.1、および.NET Framework 5.0(プレビュー)から始まるメソッドをKeyValuePair<TKey, TValue>実装Deconstructします。

これにより、KeyValuePair不可知論的な方法で辞書を反復処理することが可能です。

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

// ...

foreach (var (key, value) in dictionary)
{
    // ...
}

-1

linqでシンプル

 Dictionary<int, string> dict = new Dictionary<int, string>();
 dict.Add(1, "American Ipa");
 dict.Add(2, "Weiss");
 dict.ToList().ForEach(x => Console.WriteLine($"key: {x.Key} | value: {x.Value}") );

はクラスでのみ定義されているToList()ため、あなたは電話をかけているようですが、なぜそれだけでなくすべてを行うのですか?それはさらに簡単で、同じメモリ/パフォーマンスの影響はありません。とにかく、この正確なソリューションは、3.5年前のこの回答ですでに提案されていますForEach()List<>foreach (var pair in dict) { }
BACON

コードの視覚化のためだけに、実際にあなたが示した方法でそれを行うことができます。別の方法でそれを提示したかっただけであり、よりスリムな見方で、示された答えが表示されないことをお詫び申し上げます
Luiz Fernando Corraa Leite

-3

使用の間で議論がある最高ランクの投稿に加えて

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
}

5
2番目の辞書を作成してコピーすることは、コードを読みやすくするための有効な解決策ではありません。実際、「最後の男がなぜ2番目の辞書を作成したのか」と自問する必要があるため、コードを理解するのが難しくなると私は主張します。もっと冗長にしたい場合は、オプション1を使用してください。
Matthew Goulart

foreachの前にdictが宣言されている場合、foreachでの使用法は宣言から明らかであることを示すだけ
でした
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.