[英]Counter in foreach loop in C#
foreach的工作:据我所知,
foreach是一个循环,它逐个遍历集合或数组,从0索引开始直到集合的最后一项。
所以,如果我在数组中有n个项目。
foreach (var item in arr)
{
}
然后,在第一次迭代中, item = arr [0];
然后,在第2, item = arr [1];
。
。
。
在last(nth), item = arr [n-1];
结论:从工作开始,它似乎在每次迭代时都知道从数组中取出哪个值,或者它知道要从数组中获取的项的索引。
现在我的问题是:如何在不使用新变量的情况下获取项目的索引?
foreach (string item in mylist)
{
if (item == "myitem")
{
// get index of item
break;
}
}
这取决于你的意思“它”。 迭代器知道它到达了什么索引,是 - 在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:
- 使用语句体运行你的逻辑。
- 因为返回false ,新的可枚举数据计数为零。
- 使用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 |
并非所有集合都有索引。 例如,我可以使用带foreach
的Dictionary
(并遍历所有键和值),但我不能使用dictionary[0]
, dictionary[1]
等来编写单个元素。
如果我确实想要遍历字典并跟踪索引,我必须使用一个单独的变量,我自己增加。
在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
}
}
}
来自MSDN:
foreach语句为数组中的每个元素或实现System.Collections.IEnumerable或System.Collections.Generic.IEnumerable(Of T)接口的对象集合重复一组嵌入式语句。
所以,它不一定是Array。 它甚至可能是一个懒惰的集合,不知道集合中的项目数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.