foreachの動作:私が知っているように、
foreachは、インデックス0からコレクションの最後のアイテムまで、コレクションまたは配列を1つずつ繰り返すループです
したがって、配列にn個のアイテムがある場合。
foreach (var item in arr)
{
}
次に、In、1回目の反復、item = arr [0];
次に、2番目に、item = arr [1];
。
。
。
in last(nth)、item = arr [n-1];
結論:動作から、各反復で、配列から取得する値または配列から取得するアイテムのインデックスを知っているようです。
今私の質問:新しい変数を使用せずにアイテムのインデックスを取得するにはどうすればよいですか?
foreach (string item in mylist)
{
if (item == "myitem")
{
// get index of item
break;
}
}
「it」の意味に依存します。イテレータは、到達したインデックスを知っています、はい-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
クラスを使用します。これは前のオプションに少し似ています
これらのオプションの最初を除くすべては、コレクションが自然にインデックス付けされているかどうかにかかわらず機能します。
for
の代わりにforeach
を使用します。 foreach
はその内部の動作を公開せず、IEnumerable
(インデックスをまったく必要としない)であるものをすべて列挙します。
_for (int i=0; i<arr.Length; i++)
{
...
}
_
また、リスト内の特定のアイテムのインデックスを見つけようとしている場合は、自分でそれを繰り返す必要はありません。代わりにArray.IndexOf(item)
を使用してください。
foreach
の理解が不完全です。
IEnumerable
を公開する(またはGetEnumerable
メソッドを実装する)任意のタイプで動作し、返されたIEnumerator
を使用してコレクション内のアイテムを反復処理します。
Enumerator
がこれを行う方法(インデックス、yield
ステートメントまたはマジックを使用)は、実装の詳細です。
目的を達成するには、for
ループを使用する必要があります。
for (int i = 0; i < mylist.Count; i++)
{
}
注意:
リスト内のアイテム数の取得は、リストのタイプによってわずかに異なります
For Collections: Use Count [property]
For Arrays: Use Length [property]
For IEnumerable: Use Count() [Linq method]
または、多くのlinqを使用したくなく、何らかの理由でforループを使用したくない場合は、さらに簡単です。
int i = 0;
foreach(var x in arr)
{
//Do some stuff
i++;
}
おそらく無意味ですが、...
foreach (var item in yourList.Select((Value, Index) => new { Value, Index }))
{
Console.WriteLine("Value=" + item.Value + ", Index=" + item.Index);
}
これは、配列を反復処理する場合にのみ当てはまります。インデックスによるアクセスの概念を持たない別の種類のコレクションを繰り返し処理している場合はどうでしょうか?配列の場合、インデックスを保持する最も簡単な方法は、単にVanilla forループを使用することです。
_datas.Where((data, index) =>
{
//Your Logic
return false;
}).Any();
_
いくつかの単純なケースでは、私の方法は_where + false + any
_を使用しています。
それはforeach + select((data,index)=>new{data,index})
より少し致命的で、カスタムのForeachメソッドはありません。
MyLogic:
- statement bodyを使用してロジックを実行します。
- falseを返すであるため、新しいEnumrableデータカウントはゼロです。
- Any() yeildを実行させます。
_[RPlotExporter, RankColumn]
public class BenchmarkTest
{
public static IEnumerable<dynamic> TestDatas = Enumerable.Range(1, 10).Select((data, index) => $"item_no_{index}");
[Benchmark]
public static void ToArrayAndFor()
{
var datats = TestDatas.ToArray();
for (int index = 0; index < datats.Length; index++)
{
var result = $"{datats[index]}{index}";
}
}
[Benchmark]
public static void IEnumrableAndForach()
{
var index = 0;
foreach (var item in TestDatas)
{
index++;
var result = $"{item}{index}";
}
}
[Benchmark]
public static void LinqSelectForach()
{
foreach (var item in TestDatas.Select((data, index) => new { index, data }))
{
var result = $"{item.data}{item.index}";
}
}
[Benchmark]
public static void LinqSelectStatementBodyToList()
{
TestDatas.Select((data, index) =>
{
var result = $"{data}{index}";
return true;
}).ToList();
}
[Benchmark]
public static void LinqSelectStatementBodyToArray()
{
TestDatas.Select((data, index) =>
{
var result = $"{data}{index}";
return true;
}).ToArray();
}
[Benchmark]
public static void LinqWhereStatementBodyAny()
{
TestDatas.Where((data, index) =>
{
var result = $"{data}{index}";
return false;
}).Any();
}
}
class Program
{
static void Main(string[] args)
{
var summary = BenchmarkRunner.Run<BenchmarkTest>();
System.Console.Read();
}
}
_
_ Method | Mean | Error | StdDev | Rank |
------------------------------- |---------:|----------:|----------:|-----:|
ToArrayAndFor | 4.027 us | 0.0797 us | 0.1241 us | 4 |
IEnumrableAndForach | 3.494 us | 0.0321 us | 0.0285 us | 1 |
LinqSelectForach | 3.842 us | 0.0503 us | 0.0471 us | 3 |
LinqSelectStatementBodyToList | 3.822 us | 0.0416 us | 0.0389 us | 3 |
LinqSelectStatementBodyToArray | 3.857 us | 0.0764 us | 0.0785 us | 3 |
LinqWhereStatementBodyAny | 3.643 us | 0.0693 us | 0.0712 us | 2 |
_
すべてのコレクションにインデックスがあるわけではありません。たとえば、Dictionary
をforeach
とともに使用できます(そしてすべてのキーと値を反復処理できます)が、_dictionary[0]
_、_dictionary[1]
_など.
辞書を反復処理してインデックスを追跡したい場合は、自分でインクリメントした別の変数を使用する必要があります。
Foreachループで繰り返されるシーケンスは、インデックス付けをサポートしていないか、実装を必要としないが、少なくともIEnumeratorのインターフェイスを持つオブジェクトを返すGetEnumeratorと呼ばれるメソッドを実装する必要があるような概念を知っていない場合があります。繰り返し処理がインデックス作成をサポートし、インデックスが必要なことがわかっている場合は、代わりにfor
ループを使用することをお勧めします。
foreach
で使用できるサンプルクラス:
class Foo {
public iterator GetEnumerator() {
return new iterator();
}
public class iterator {
public Bar Current {
get{magic}
}
public bool MoveNext() {
incantation
}
}
}
MSDNから:
Foreachステートメントは、System.Collections.IEnumerableまたはSystem.Collections.Generic.IEnumerable(Of T)インターフェイスを実装する配列またはオブジェクトコレクションの各要素に対して、埋め込みステートメントのグループを繰り返します。
したがって、必ずしも配列ではありません。コレクション内のアイテムの数がわからない、怠collectionなコレクションでさえあり得ます。