Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there an equivalent to Python's enumerate() for .NET IEnumerable

I could not find a related question.

In python you can easily loop through a sequence (list, generator etc) and collect the index of the iteration at the same time thanks to enumerate(seq) like this :

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

Is there something similar for IEnumerable, that would, for instance, transform a IEnumerable<T> in a IEnumerable<Tuple<Int32,T>> ?

(I know it would be easily done thanks to the correct function in Select() .. but if it exists, I'd rather use it :) )

UPDATE FYI, I am curious about this kind of possibility to be able to do something like : "give me the index of the last item that fulfils this condition", which would then be accomplished through :

myEnumeration.First(t => some condition on t.Item2 ... ).Item1;
like image 976
tsimbalar Avatar asked Sep 12 '11 13:09

tsimbalar


People also ask

Is range Len faster than enumerate?

enumerate() is faster when you want to repeatedly access the list/iterable items at their index. When you just want a list of indices, it is faster to use len() and range().

What is Python IEnumerable?

IEnumerable is an interface whose purpose is to provide a way to iterate over a collection. It is one of the most basic and widely used collection interfaces in . NET and implemented by pretty much every collection type (arrays, lists, hashsets, dictionaries, bags, … you name it).

What does enumerate () do in Python?

Python enumerate() Function The enumerate() function takes a collection (e.g. a tuple) and returns it as an enumerate object. The enumerate() function adds a counter as the key of the enumerate object.

Is enumerate 0 based?

As in the example above, by default, the index of enumerate() starts at 0. If you want to start from another number, pass the number to the second argument of enumerate() . For example, this is useful when generating sequential number strings starting from 1.


2 Answers

C# 7 finally allows you to do this in an elegant way:

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}");
    }
}
like image 178
Paul Mitchell Avatar answered Sep 30 '22 17:09

Paul Mitchell


Instead of using a Tuple<,> (which is a class) you can use a KeyValuePair<,> which is a struct. This will avoid memory allocations when enumerated (not that they are very expensive, but still).

public static IEnumerable<KeyValuePair<int, T>> Enumerate<T>(this IEnumerable<T> items) {
    return items.Select((item, key) => new KeyValuePair(key, item));
}
like image 27
Lucero Avatar answered Sep 30 '22 18:09

Lucero