C# 带索引的foreach
有没有一个C#等价于Python的C# 带索引的foreach,c#,foreach,C#,Foreach,有没有一个C#等价于Python的enumerate()和Ruby的的C#等价物,每个C#等价物都有索引。您需要在foreach循环外添加一个整数,并每次递增 int i = -1; foreach (Widget w in widgets) { i++; // do something } 或者,您可以使用标准for循环,如下所示: for (int i = 0; i < widgets.Length; i++) { w = widgets[i]; // do
enumerate()
和Ruby的的C#等价物,每个C#等价物都有索引
。您需要在foreach循环外添加一个整数,并每次递增
int i = -1;
foreach (Widget w in widgets)
{
i++;
// do something
}
或者,您可以使用标准for循环,如下所示:
for (int i = 0; i < widgets.Length; i++)
{
w = widgets[i];
// do something
}
for(inti=0;i
这取决于您使用的类
例如,Dictionary)类支持这一点
字典)泛型类提供从一组键到一组值的映射
出于枚举目的,字典中的每个项都被视为表示值及其键的KeyValuePair(KeyValuePair)结构。返回项目的顺序未定义
foreach(myDictionary中的KeyValuePair kvp){…}您可以执行以下操作
foreach (var it in someCollection.Select((x, i) => new { Value = x, Index = i }) )
{
if (it.Index > SomeNumber) //
}
这将为集合中的每个条目创建一个匿名类型值。它将有两个属性
:集合中的原始值值
:索引位于集合中索引
我们可能可以在非泛型类型中使用静态方法改进类型推断,隐式类型也会有所帮助。我的解决方案涉及我为通用工具创建的一个简单的Pair类,它在操作上与框架类KeyValuePair基本相同。然后我为IEnumerable创建了两个扩展函数,称为纵坐标(源自集合论术语“”) 这些函数将为每个项返回一个包含索引和项本身的Pair对象
public static IEnumerable<Pair<Int32, X>> Ordinate<X>(this IEnumerable<X> lhs)
{
return lhs.Ordinate(0);
}
public static IEnumerable<Pair<Int32, X>> Ordinate<X>(this IEnumerable<X> lhs, Int32 initial)
{
Int32 index = initial - 1;
return lhs.Select(x => new Pair<Int32, X>(++index, x));
}
公共静态IEnumerable坐标(此IEnumerable lhs)
{
返回左纵坐标(0);
}
公共静态IEnumerable坐标(此IEnumerable lhs,Int32首字母)
{
Int32指数=初始值-1;
返回lhs.Select(x=>newpair(++索引,x));
}
不,没有
正如其他人所展示的,有很多方法可以模拟Ruby的行为。但也可以有一个实现不公开索引的类型。我保留此扩展方法用于:
public static void Each<T>(this IEnumerable<T> ie, Action<T, int> action)
{
var i = 0;
foreach (var e in ie) action(e, i++);
}
我刚刚想出了一个有趣的解决方案:
public class DepthAware<T> : IEnumerable<T>
{
private readonly IEnumerable<T> source;
public DepthAware(IEnumerable<T> source)
{
this.source = source;
this.Depth = 0;
}
public int Depth { get; private set; }
private IEnumerable<T> GetItems()
{
foreach (var item in source)
{
yield return item;
++this.Depth;
}
}
public IEnumerator<T> GetEnumerator()
{
return GetItems().GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
// Generic type leverage and extension invoking
public static class DepthAware
{
public static DepthAware<T> AsDepthAware<T>(this IEnumerable<T> source)
{
return new DepthAware<T>(source);
}
public static DepthAware<T> New<T>(IEnumerable<T> source)
{
return new DepthAware<T>(source);
}
}
这是你的收藏
var values = new[] {6, 2, 8, 45, 9, 3, 0};
var indexes = Enumerable.Range(0, values.Length).ToList();
为此集合创建一系列索引
var values = new[] {6, 2, 8, 45, 9, 3, 0};
var indexes = Enumerable.Range(0, values.Length).ToList();
使用范围与索引进行迭代
indexes.ForEach(i => values[i] += i);
indexes.ForEach(i => Console.Write("[{0}] = {1}", i, values[i]));
我喜欢能够使用foreach,因此我制作了一个扩展方法和结构:
public struct EnumeratedInstance<T>
{
public long cnt;
public T item;
}
public static IEnumerable<EnumeratedInstance<T>> Enumerate<T>(this IEnumerable<T> collection)
{
long counter = 0;
foreach (var item in collection)
{
yield return new EnumeratedInstance<T>
{
cnt = counter,
item = item
};
counter++;
}
}
一件好事是,如果您习惯了Python语法,您仍然可以使用它:
foreach (var ii in Enumerate(new string[] { "a", "b", "c" }))
我认为您应该将I初始化为-1,并在循环体的开始处递增,以确保“continue”语句不会引起问题。@DrJokepu为什么不简单地保持I=0,并在foreach语句的结束括号之前递增它呢?正在初始化某些内容!=当您稍后浏览代码时,0会引起注意…使用JavaScriptSmart,但这就像用右手抓左耳一样。我想我会自己保存索引,这样我就不会把未来的维护者弄糊涂了。@Neil,人们认为这是一个维护问题,我很惊讶。Select(和其他LINQ方法)的重载完全是为了完成这样的操作而提供的。我看不到维护方面的问题。如果未来的维护人员无法查看MSDN文档并查找Select方法的重载,那就是他们自己的问题。担心变量名?只需执行:(Value,Index)=>为lambda选择新的{Value,Index}。@Lodewijk没有支持集合,
IEnumerable.ElementAt(i)
是O(n)(请参阅)。如果您有一个惰性的枚举表,它的计算代价很高,并且包含大量的记录,该怎么办?对于for循环,您必须等待IEnumerable.Count()
返回,然后才能开始处理记录。for循环通常不适合与IEnumerable
一起使用。当使用C#7值元组时,这可能会缩短一点:foreach(在某个集合中的var(x,i)。Select((x,i)=>(x,i)){…}
您不能打断这个foreach循环。这是因为它不是foreach循环。@TriQ这只是喜欢它的另一个原因,大部分时间。:)@丹芬奇:我不是在咆哮,我是在合法地寻找答案。@TankorSmash这是一种“扩展方法”。看看这个。有点可怕的C#魔法。太棒了!这些小助手属性(first/last/index)应该包含在标准的.net框架中!这是伟大的,我只是不喜欢它的长和非描述性的名称链接似乎是死的。我能找到的最好的链接是(对于包含的库)和Jon讨论它的博客。@RobinMacharg:我编辑了链接,谢谢。如果您使用LINQ,则有允许枚举的各种函数的重写。否则,您通常无法使用自己递增的变量。我们是否可以将此问题更新为C#7.0,其中现在有元组?我想知道使用元组的解决方案会是什么样子。不是吗“难道你不能用foreach
的一项功能来处理每个元素,使其与列表中的位置完全解耦吗?请注意,现在你的对有一个系统。Tuple
。复活一个僵尸,因为我只需要这样做:如果枚举被多次迭代,这将表现得很混乱。你是对的。如果我今天要实现这一点,我肯定会接受公认的答案。最后一部分在您看来是Python语法的哪一部分?很抱歉发布了这篇文章。我修改了你的函数,使它看起来更漂亮,在使用中更具python风格:
foreach (var ii in new string[] { "a", "b", "c" }.Enumerate())
{
Console.WriteLine(ii.item + ii.cnt);
}
foreach (var ii in Enumerate(new string[] { "a", "b", "c" }))