对于.NET IEnumerable,是否有相当于Python的enumerate()

tsi*_*lar 5 .net ienumerable

我找不到相关的问题.

python你可以很容易地通过一个序列(循环list,generator等等),并收集迭代的索引,同时由于在以enumerate(seq)这样的:

>>> for (i,item) in enumerate(["toto","titi","tutu"]):
...     print i, item
...
0 toto
1 titi
2 tutu
Run Code Online (Sandbox Code Playgroud)

IEnumerable是否有类似的东西,例如,会变换IEnumerable<T>a IEnumerable<Tuple<Int32,T>>

(我知道它很容易完成,这要归功于Select()......中的正确功能,但如果它存在,我宁愿使用它:))

更新 FYI,我很好奇能够做出类似的事情:"给我满足这个条件的最后一项的索引",然后通过以下方式完成:

myEnumeration.First(t => some condition on t.Item2 ... ).Item1;
Run Code Online (Sandbox Code Playgroud)

Pau*_*ell 8

C# 7 终于允许你以一种优雅的方式做到这一点:

static class Extensions
{
    public static IEnumerable<(int, T)> Enumerate<T>(
        this IEnumerable<T> input,
        int start = 0
    )
    {
        int i = start;
        foreach (var t in input)
            yield return (i++, t);
    }
}

class Program
{
    static void Main(string[] args)
    {
        var s = new string[]
        {
            "Alpha",
            "Bravo",
            "Charlie",
            "Delta"
        };

        foreach (var (i, o) in s.Enumerate())
            Console.WriteLine($"{i}: {o}");
    }
}
Run Code Online (Sandbox Code Playgroud)


Luc*_*ero 6

Tuple<,>您可以使用 a KeyValuePair<,>which 作为结构,而不是使用 a (这是一个类)。这将避免枚举时的内存分配(不是它们非常昂贵,但仍然如此)。

public static IEnumerable<KeyValuePair<int, T>> Enumerate<T>(this IEnumerable<T> items) {
    return items.Select((item, key) => new KeyValuePair(key, item));
}
Run Code Online (Sandbox Code Playgroud)


Mic*_*ael 5

至于将执行您所要求的特定功能,我不知道 .NET 是否包含它。然而,最快的方法就是做这样的事情:

int id = 0;
foreach(var elem in someList)
{
    ... doStuff ...
    id++;
}
Run Code Online (Sandbox Code Playgroud)

编辑:这是一个可以按照您的要求执行的函数,使用yield return,但它的缺点是每次迭代需要一个 GC 分配:

public static IEnumerable<Tuple<int, T>> Enumerate<T>(IEnumerable<T> list)
{
    int id = 0;
    foreach(var elem in list)
    {
        yield return new Tuple<int, T>(id, elem);
        id++;
    }
}
Run Code Online (Sandbox Code Playgroud)