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

时间:2011-09-12 13:56:30

标签: .net python ienumerable

我找不到相关的问题。

python中,您可以轻松遍历序列(listgenerator等)并同时收集迭代索引,这要归功于enumerate(seq)这样:

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

IEnumerable是否有类似内容,例如,会转换IEnumerable<T>中的IEnumerable<Tuple<Int32,T>>

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

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

myEnumeration.First(t => some condition on t.Item2 ... ).Item1;

5 个答案:

答案 0 :(得分:4)

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

int id = 0;
foreach(var elem in someList)
{
    ... doStuff ...
    id++;
}

编辑:这是一个函数,可以按照您的要求使用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++;
    }
}

答案 1 :(得分:3)

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

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

答案 2 :(得分:2)

这是我自己对自己问题的回答......

如果它不存在,我可以这样做,而不是实际写for / foreach

var items = new List<String> { "toto", "titi", "tutu" };

var enumerated = items.Select((x, i) => new Tuple<int, String>(i, x));

foreach (var t in enumerated)
{
    Console.WriteLine(String.Format("{0} : {1}", t.Item1, t.Item2));

}

打印:

0 : toto
1 : titi
2 : tutu

这是一个单行程......一个丑陋的,但无论如何都是单行:)

答案 3 :(得分:1)

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}");
    }
}

答案 4 :(得分:0)

这是一个扩展方法,它将返回元组序列,其中第一项是序列中的数字,第二项是源序列中的值。

public static IEnumerable<Tuple<int, T>> Enumerate<T>(this IEnumerable<T> source, int start = 0)
{
    return source.Select((value, index) => new Tuple<int, T>(index + start, value));
}

示例:     

var source = new[] { "apple", "pear", "banana", "orange", "lemon" };
var enumerated1 = source.Enumerate();   // { (0, "apple"), (1, "pear"), (2, "banana"), (3, "orange"), (4, "lemon") }
var enumerated2 = source.Enumerate(3);  // { (3, "apple"), (4, "pear"), (5, "banana"), (6, "orange"), (7, "lemon") }