Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 带索引的foreach_C#_Foreach - Fatal编程技术网

C# 带索引的foreach

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

有没有一个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 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) //      
}
这将为集合中的每个条目创建一个匿名类型值。它将有两个属性

  • :集合中的原始值
  • 索引
    :索引位于集合中

除了已经给出的LINQ答案之外,我还有一个类,可以让你获得索引和“第一/最后”属性。它的语法有点难看,但您可能会发现它很有用


我们可能可以在非泛型类型中使用静态方法改进类型推断,隐式类型也会有所帮助。

我的解决方案涉及我为通用工具创建的一个简单的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" }))