How to get the index of an element in an IEnumerable?

Related searches

I wrote this:

public static class EnumerableExtensions
{
    public static int IndexOf<T>(this IEnumerable<T> obj, T value)
    {
        return obj
            .Select((a, i) => (a.Equals(value)) ? i : -1)
            .Max();
    }

    public static int IndexOf<T>(this IEnumerable<T> obj, T value
           , IEqualityComparer<T> comparer)
    {
        return obj
            .Select((a, i) => (comparer.Equals(a, value)) ? i : -1)
            .Max();
    }
}

But I don't know if it already exists, does it?

The whole point of getting things out as IEnumerable is so you can lazily iterate over the contents. As such, there isn't really a concept of an index. What you are doing really doesn't make a lot of sense for an IEnumerable. If you need something that supports access by index, put it in an actual list or collection.

How to get item from IEnumerable collection using its index in C , ElementAt(i);. If you want to enumerate the entire collection, but also want to have an index for each element, then V.A.'s or Nestor's� public static class EnumerableExtensions { public static int IndexOf<T>(this IEnumerable<T> obj, T value) { return obj.IndexOf(value, null); } public static int IndexOf<T>(this IEnumerable<T> obj, T value, IEqualityComparer<T> comparer) { comparer = comparer ??

I'd question the wisdom, but perhaps:

source.TakeWhile(x => x != value).Count();

(using EqualityComparer<T>.Default to emulate != if needed) - but you need to watch to return -1 if not found... so perhaps just do it the long way

public static int IndexOf<T>(this IEnumerable<T> source, T value)
{
    int index = 0;
    var comparer = EqualityComparer<T>.Default; // or pass in as a parameter
    foreach (T item in source)
    {
        if (comparer.Equals(item, value)) return index;
        index++;
    }
    return -1;
}

How to access index in IEnumerable object in C#?, index is less than 0 or greater than or equal to the number of elements in source . Examples. The following code example demonstrates how to use ElementAt to� Cannot apply indexing with [] to an expression of type ‘System.Collections.Generic.IEnumerable<T>. But there is the extension method ElementAt(index) (in the System.Linq namespace) for IEnumerable<T> that will allow you to get at that particular indexed item: MyItem = MyIEnumerableExpression.ElementAt(index);

I would implement it like this:

public static class EnumerableExtensions
{
    public static int IndexOf<T>(this IEnumerable<T> obj, T value)
    {
        return obj.IndexOf(value, null);
    }

    public static int IndexOf<T>(this IEnumerable<T> obj, T value, IEqualityComparer<T> comparer)
    {
        comparer = comparer ?? EqualityComparer<T>.Default;
        var found = obj
            .Select((a, i) => new { a, i })
            .FirstOrDefault(x => comparer.Equals(x.a, value));
        return found == null ? -1 : found.i;
    }
}

Enumerable.ElementAt<TSource>(IEnumerable , Searches for the specified object and returns the zero-based index of the first occurrence within the range of elements in the List<T> that extends from the� A collection of IEnumerable<T> has no indexing, so there’s no direct method to find an item’s index. LINQ, as powerful as it is, gives us many tools to get us this information, but not in one step.

The way I'm currently doing this is a bit shorter than those already suggested and as far as I can tell gives the desired result:

 var index = haystack.ToList().IndexOf(needle);

It's a bit clunky, but it does the job and is fairly concise.

List<T>.IndexOf Method, A collection of IEnumerable<T> has no indexing, so there's no direct method to find an item's index. LINQ, as powerful as it is, gives us many� If the type of source implements IList<T>, that implementation is used to obtain the element at the specified index. Otherwise, this method obtains the specified element. This method throws an exception if index is out of range. To instead return a default value when the specified index is out of range, use the ElementAtOrDefault method. Applies to

The best way to catch the position is by FindIndex This function is available only for List<>

Example

int id = listMyObject.FindIndex(x => x.Id == 15); 

If you have enumerator or array use this way

int id = myEnumerator.ToList().FindIndex(x => x.Id == 15); 

or

 int id = myArray.ToList().FindIndex(x => x.Id == 15); 

C#/.NET Fundamentals: Finding an Item's Index in IEnumerable<T>, Use the .ToArray method to convert an IEnumerable to an array. This approach would be the easiest, in my opinion. If you want to use the IEnumerables, however, here is some sample code for you: ienumerable.xaml (9.9 KB) You can loop through 2 IEnumerables at the same time if you get their IENumerator, using the .GetEnumerator method

var item = eLevelData.ElementAt(index); If your collection is typed as IEnumerable instead of IEnumerable<T> you'll need to use the Cast extension method before you can call ElementAt e.g. var item = eLevelData.Cast<RMSRequestProcessor.RMSMedia>().ElementAt(index)

I often want to grab the first element of an IEnumerable<T> in .net, and I haven't found a nice way to do it. (Object items, int index) where T : class { T item

If the type of source implements ICollection<T>, that implementation is used to obtain the count of elements. Otherwise, this method determines the count. Use the LongCount method when you expect and want to allow the result to be greater than MaxValue.

Comments
  • The problem with a Max approach is that a: it keeps looking, and b: it returns the last index when there are duplicates (people usually expect the first index)
  • geekswithblogs.net compares 4 solutions and their performance. The ToList()/FindIndex() trick performs best
  • Currently I came accross this thread because I'm implementing a generic IList<> wrapper for the IEnumerable<> type in order to use my IEnumerable<> objects with third party components which only support datasources of type IList. I agree that trying to get an index of an element within an IEnumerable object is probably in most cases a sign of something beign done wrong there are times when finding such index once beats reproducing a large collection in memory just for the sake of finding the index of a single element when you already have an IEnumerable.
  • -1 cause: There are legitimate reasons why you want to get an index out of a IEnumerable<>. I don't buy the whole "you shoul'd be doing this" dogma.
  • Agree with @ja72; if you shouldn't be dealing with indexes with IEnumerable then Enumerable.ElementAt would not exist. IndexOf is simply the inverse -- any argument against it must apply equally to ElementAt.
  • Cleary, C# misses the concept of IIndexableEnumerable. that would just be the equivalent of an "random accessible" concept, in C++ STL terminology.
  • extensions with overloads like Select((x, i) => ...) seem to imply that these indexes should exist
  • +1 for "questioning the wisdom". 9 times out of 10 it's probably a bad idea in the first place.
  • The explicit loop solution also runs 2x faster (in the worst case) than the Select().Max() solution too.
  • You can just Count elements by lambda without TakeWhile - it saves one loop: source.Count(x => x != value);
  • @Kamarey - no, that does something different. TakeWhile stops when it gets a failure; Count(predicate) returns the ones that match. i.e. if the first was a miss and everything else was true, TakeWhile(pred).Count() will report 0; Count(pred) will report n-1.
  • TakeWhile is clever! Bear in mind though this returns Count if element doesn't exist which is a deviation from standard behaviour.
  • That's actually very cute, +1! It involves extra objects, but they should be relatively cheap (GEN0), so not a huge problem. The == might need work?