2010-12-02 12 views
33

ワーキング: 私が知っているように、C#でforeachループでカウンター

foreachのは まで0インデックスから始まる ずつコレクションまたは配列1を反復処理し、ループでありますコレクションの最後の項目。

したがって、配列にn個のアイテムがあるとします。

foreach (var item in arr) 
{ 

} 

次いで、 において、第1の反復、アイテム=のARR [0]。
次に、2番目に、item = arr [1];



最後に(nth)、item = arr [n-1];

結論:を作業から各反復で、それがアレイから採取すべき値のことを知っているか、アレイから採取する項目のインデックスを知っていると思われます。

私の質問新しい変数を使用せずに項目のインデックスを取得するにはどうすればよいですか?

foreach (string item in mylist) 
{ 
    if (item == "myitem") 
    { 
     // get index of item 
     break; 
    } 
} 
+0

カノニカルな質問は* [どのようにforeachループの現在の反復のインデックスを取得しますか?*(http://stackoverflow.com/questions/43021)*。 –

+1

可能な複製* [どのようにforeachループの現在の反復のインデックスを取得しますか?](http://stackoverflow.com/questions/43021/how-do-you-get-the-index-of-the -current-iteration-of-a-foreach-loop)*です。 –

答えて

69

「それ」の意味によって異なります。イテレータは、どのインデックスに到達したかを知っています(List<T>または配列の場合)。しかし、IEnumerator<T>には一般的なインデックスはありません。インデックス化されたコレクションを反復処理するかどうかは実装次第です。コレクションの多くは直接インデックス作成をサポートしていません。

foreachは、常にすべてのイテレータを使用していません。コレクションのコンパイル時の型が配列の場合は実際には、コンパイラはarray[0]を使用して、それを反復し、array[1]など同様にコレクションを持つことができますこの方法は、適切なメンバーと型を返すGetEnumerator()と呼ばれるが、視力のIEnumerable/IEnumeratorの任意の実装)インデックスを維持するため

オプションなし:

  • forループを使用
  • 別の変数を使用する
  • 各アイテムをインデックス/値のペアに投影する投影法を使用します。

    foreach (var x in list.Select((value, index) => new { value, index })) 
    { 
        // Use x.value and x.index in here 
    } 
    
  • 少し前のオプション

すべてのようなものですが、これらのオプションの最初のコレクションは、自然に索引付けされているかどうか動作します私のSmartEnumerableクラスを使用します。

+0

@Downvoter:コメントしますか? –

+0

Jon ......私はあなたの答えの大ファンです。 – AlwaysAProgrammer

+1

あなたの投影アプローチはエレガントでシンプルですが、私はそれを挟んでいます! – madman1969

17

利用forの代わりforeachforeachは内部動作を公開していませんが、IEnumerable(インデックスを持つ必要はありません)というものをすべて列挙します。あなたが何をしようとしていることは、リスト内の特定の項目のインデックスを見つけることである場合

for (int i=0; i<arr.Length; i++) 
{ 
    ... 
} 

ほかに、あなたは自分ですべてでそれを反復処理する必要はありません。代わりにArray.IndexOf(item)を使用してください。

+0

私はそれが私が JasonS

+0

おっとするべきだと思います。それはもちろん正しいことです。ありがとう。 –

+0

他の回答で数回述べたように、foreachで動作するにはIEnumerableでなければなりません。 –

1

これは、配列を反復処理する場合にのみ当てはまります。インデックス別アクセスの概念がない別の種類のコレクションを反復処理していた場合はどうなりますか?配列の場合、インデックスを保持する最も簡単な方法は、単純にforループを使用することです。

10

foreachのご理解は不完全です。

IEnumerable(またはGetEnumerableメソッドを実装する)を公開し、返されたIEnumeratorを使用してコレクション内のアイテムを反復処理する任意のタイプで機能します。

Enumeratorが(インデックス、yieldのステートメントまたはマジックを使用して)これを行う方法は、実装の詳細です。

for (int i = 0; i < mylist.Count; i++) 
{ 
} 

注:

あなたが望むものを達成するために、あなたはforループを使用する必要があり

リスト内の項目数を取得するタイプによって若干異なりますリストの一覧

For Collections: Use Count [property] 
For Arrays:  Use Length [property] 
For IEnumerable: Use Count() [Linq method] 
+0

私はそれが魔法だと思います。 – Brad

+0

'foreach'は実際に' GetEnumerator'メソッドを持つ型で動作します(そのメソッドが適切な 'Current'プロパティと' MoveNext'メソッドを持つオブジェクトを返した場合)。型は実際には 'IEnumerable' /' IEnumerator'を実装する必要はありません。 – LukeH

+0

@ルークH - フェアポイント。回答が更新されました。 – Oded

0

すべてのコレクションにインデックスがあるわけではありません。例えば、私はforeachDictionaryを使用することができます(そして、すべてのキーと値を反復処理)が、私はdictionary[0]を使用して、個々の要素の取得時の書き込みはできません、dictionary[1]など

私は辞書を反復処理したいなかった場合インデックスを把握しておくと、別の変数を使用して自分自身を増やす必要があります。

2

foreach (var item in yourList.Select((Value, Index) => new { Value, Index })) 
{ 
    Console.WriteLine("Value=" + item.Value + ", Index=" + item.Index); 
} 
0

foreachループ内で反復処理されたシーケンスがインデックス作成をサポートしたり、それは同じようにそのオブジェクトを返すGetEnumeratorメソッドと呼ばれるメソッドを実装する必要があり、このような概念を知らないかもしれないおそらく無意味な、しかし...最低限、IEnumeratorのインターフェイスがありますが、それは必須ではないことを暗示しています。あなたが反復するものがインデックス作成をサポートし、インデックスが必要であることがわかっている場合は、代わりにforループを使用することをお勧めします。foreachで使用することができる

例えばクラス:

class Foo { 

     public iterator GetEnumerator() { 
      return new iterator(); 
     } 

     public class iterator { 
      public Bar Current { 
       get{magic} 
      } 

      public bool MoveNext() { 
       incantation 
      } 
     } 
    } 
+0

'GetEnumerator()'は、IEnumerator'を実装する型を返す必要もありません... –

+0

@Jon Skeet:どういう意味ですか? IEnumerator GetEnumerator(); 'IEnumerable'内で定義された唯一のメソッドのシグネチャはありませんか? –

+0

@ Yodan:はい、でもIEnumerableを実装する必要はありません:) –

0

MSDNから:

foreachステートメントは、配列またはオブジェクトの各 要素のグループの埋め込み文の を繰り返します System.Collections.IEnumerableまたは を実装しているコレクション System.Collections.Generic.IEnumerable(Of T)インターフェース。

したがって、必ずしも配列ではありません。それは、コレクション内のアイテムの数が分からない、怠惰なコレクションでもあります。

5

さらに多くのlinqを使いたくない場合や、何らかの理由でforループを使用したくない場合はさらに簡単です。

int i = 0; 
foreach(var x in arr) 
{ 
    //Do some stuff 
    i++; 
} 
+0

人生はシンプルです –

+0

'arr.Length'コレクションとして、foreach(var x in arr)であると思われますか? – karthick

+0

@karthick - それはほぼ4年前に書かれましたが、あなたはもちろん正しいです。 。:)もし私がまだできれば、編集しましょう。 – BlueVoodoo