foreach with index

Ken*_*Ken 150 c# foreach

是否有C#相当于Python enumerate()和Ruby each_with_index

Dan*_*Dan 260

我保留了这个扩展方法:

public static void Each<T>(this IEnumerable<T> ie, Action<T, int> action)
{
    var i = 0;
    foreach (var e in ie) action(e, i++);
}
Run Code Online (Sandbox Code Playgroud)

并像这样使用它:

var strings = new List<string>();
strings.Each((str, n) =>
{
    // hooray
});
Run Code Online (Sandbox Code Playgroud)

或者允许break类似行为:

public static bool Each<T>(this IEnumerable<T> ie, Func<T, int, bool> action)
{
    int i = 0;
    foreach (T e in ie) if (!action(e, i++)) return false;
    return true;
}

var strings = new List<string>() { "a", "b", "c" };

bool iteratedAll = strings.Each ((str, n)) =>
{
    if (str == "b") return false;
    return true;
});
Run Code Online (Sandbox Code Playgroud)

  • 你不能打破这个foreach循环. (29认同)
  • 那是因为它不是一个foreach循环. (24认同)
  • @TriQ这是大多数时候喜欢它的另一个原因.:) (6认同)
  • @TankorSmash这是一个"扩展方法".看看这个.有点令人敬畏的C#魔术. (2认同)

Jar*_*Par 205

您可以执行以下操作

foreach (var it in someCollection.Select((x, i) => new { Value = x, Index = i }) )
{
   if (it.Index > SomeNumber) //      
}
Run Code Online (Sandbox Code Playgroud)

这将为collect中的每个条目创建一个匿名类型值.它将有两个属性

  1. 值:具有集合中的原始值
  2. 索引:具有集合内的索引

  • @Neil,我很惊讶人们认为这是一个维护问题.Select(和其他LINQ方法)的这种重载是为了完成这样的操作的完整目的而提供的. (39认同)
  • 聪明,但就像用右手抓你的左耳.我想我会自己保留索引,所以我不会混淆未来的维护者. (13认同)
  • @Lodewijk没有支持集合,`IEnumerable <T> .ElementAt(i)`是O(n)(参见[Schlemiel the Painter](https://en.wikipedia.org/wiki/Schlemiel_the_Painter%27s_algorithm#Schlemiel_the_Painter.27s_algorithm )).如果你有一个懒惰的可枚举的评估费用并包含大量的记录呢?使用for循环,您必须等待`IEnumerable <T> .Count()`返回,然后才能开始处理记录.for循环通常不适合与`IEnumerable <T>`一起使用. (7认同)
  • 使用 C# 7 ValueTuple 时,现在可以变得更短:`foreach (var (x, i) in someCollection.Select((x, i) =&gt; (x, i)) ) { ... }` (6认同)
  • 我发现维护没有问题.如果未来的维护者无法访问MSDN文档并查找Select方法的重载,那就是他们自己的问题.担心变量名?只需:(值,索引)=>为lambda选择新的{Value,Index}. (4认同)
  • A 表示努力,但 F 表示一般可读性和维护性。对不起。 (2认同)
  • 我看到除了可能给出x之外没有维护问题,我更有用的名字.当代码插入到所需的位置时,它们显然在这里被模糊地重命名为适当的东西.如果这种类型的代码对您来说是不可读的,我只是放弃尝试任何真正简洁的语言,如C++或F#...... (2认同)
  • 这显然比经典的 for 循环更糟糕。因为它更嘈杂。更多(大)括号。更多文字阅读。到目前为止,比经典的 for 循环更难阅读和理解。 (2认同)
  • 使用非常奇怪的foreach代替通常的for循环是没有意义的。每个没有看到这是维护问题的人都应该阅读古老且语法正确的英语;相信我,惯例会有所帮助。(另:更多的字符,但性能较低) (2认同)

Dav*_*ton 59

C#foreach没有内置索引.你需要在foreach循环之外添加一个整数,并且每次都增加它.

int i = -1;
foreach (Widget w in widgets)
{
   i++;
   // do something
}
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用标准for循环,如下所示:

for (int i = 0; i < widgets.Length; i++)
{
   w = widgets[i];
   // do something
}
Run Code Online (Sandbox Code Playgroud)

  • 我认为你应该将i初始化为-1并在循环体的开头增加它,以确保"continue"语句不会导致问题. (15认同)
  • @DrJokepu为什么不简单地保持i = 0并在foreach语句的结束括号之前增加它?使用某些内容初始化!= 0会在您稍后浏览代码时触发注意... (6认同)

Dan*_*l K 16

我喜欢能够使用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++;
    }
}
Run Code Online (Sandbox Code Playgroud)

和一个使用示例:

foreach (var ii in new string[] { "a", "b", "c" }.Enumerate())
{
    Console.WriteLine(ii.item + ii.cnt);
}
Run Code Online (Sandbox Code Playgroud)

一个好处是,如果你习惯了Python语法,你仍然可以使用它:

foreach (var ii in Enumerate(new string[] { "a", "b", "c" }))
Run Code Online (Sandbox Code Playgroud)


Jon*_*eet 15

除了已经给出的LINQ答案之外,我还有一个"SmartEnumerable"类,它允许您获取索引和"第一个/最后一个" - .它在语法方面有点难看,但你可能会发现它很有用.

我们可以使用非泛型类型中的静态方法来改进类型推断,并且隐式类型也会有所帮助.

  • 大!这些小的辅助属性(first/last/index)应该包含在标准的.net框架中! (2认同)

Chr*_*man 6

我的解决方案涉及一个简单的Pair类,我为通用实用程序创建,它在操作上与框架类KeyValuePair基本相同.然后我为IEnumerable创建了一个名为Ordinate的扩展函数(来自集合论术语" 序数 ").

这些函数将为包含索引的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));
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这些天来,您的“对”有一个“ System.Tuple”。 (2认同)