如何获得IEnumerable中的元素的索引?

我写了这个:

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

但是我不知道它是否已经存在,是吗?

IEnumerable让事情变得完整的一点是,你可以懒洋洋地遍历内容。 因此,没有真正的索引概念。 你所做的事情对于IEnumerable来说确实没什么意义。 如果你需要一些支持索引访问的东西,把它放在一个实际的列表或集合中。

我会质疑智慧,但也许:

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

(使用EqualityComparer<T>.Default模拟!=如果需要的话) – 但是如果没有find,你需要注意返回-1 …所以也许只是做了很长的路要走

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

我会这样实现它:

 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(xa, value)); return found == null ? -1 : found.i; } } 

我现在这样做的方式比已经build议的要短一些,据我所知,可以给出所需的结果:

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

这有点笨重,但它的工作很简单。

我认为最好的select是像这样实施:

 public static int IndexOf<T>(this IEnumerable<T> enumerable, T element, IEqualityComparer<T> comparer = null) { int i = 0; comparer = comparer ?? EqualityComparer<T>.Default; foreach (var currentElement in enumerable) { if (comparer.Equals(currentElement, element)) { return i; } i++; } return -1; } 

它也不会创build匿名对象

游戏有点晚了,我知道…但是这是我最近做的。 它与你的稍有不同,但允许程序员指定相等操作需要的是什么(谓词)。 在处理不同的types时,我发现它非常有用,因为不pipe对象types和构build在等号运算符中的<T>如何,我都有一个通用的方法。

它也有一个非常非常小的内存占用,是非常,非常快速/高效率…如果你在乎这一点。

更糟糕的是,您只需将其添加到您的扩展名列表中即可。

无论如何…在这里。

  public static int IndexOf<T>(this IEnumerable<T> source, Func<T, bool> predicate) { int retval = -1; var enumerator = source.GetEnumerator(); while (enumerator.MoveNext()) { retval += 1; if (predicate(enumerator.Current)) { IDisposable disposable = enumerator as System.IDisposable; if (disposable != null) disposable.Dispose(); return retval; } } IDisposable disposable = enumerator as System.IDisposable; if (disposable != null) disposable.Dispose(); return -1; } 

希望这有助于某人。

几年后,但是这使用Linq,如果没有find,返回-1,不会创build额外的对象,并发现短路[而不是迭代整个IEnumerable]:

 public static int IndexOf<T>(this IEnumerable<T> list, T item) { return list.Select((x, index) => EqualityComparer<T>.Default.Equals(item, x) ? index : -1) .FirstOr(x => x != -1, -1); } 

“FirstOr”在哪里:

 public static T FirstOr<T>(this IEnumerable<T> source, T alternate) { return source.DefaultIfEmpty(alternate) .First(); } public static T FirstOr<T>(this IEnumerable<T> source, Func<T, bool> predicate, T alternate) { return source.Where(predicate) .FirstOr(alternate); } 

捕捉位置的最佳方法是通过FindIndex此函数仅适用于List<>

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

如果你有枚举或数组使用这种方式

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

要么

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

在事实之后find索引的另一种方法是包装Enumerable,有点类似于使用Linq GroupBy()方法。

 public static class IndexedEnumerable { public static IndexedEnumerable<T> ToIndexed<T>(this IEnumerable<T> items) { return IndexedEnumerable<T>.Create(items); } } public class IndexedEnumerable<T> : IEnumerable<IndexedEnumerable<T>.IndexedItem> { private readonly IEnumerable<IndexedItem> _items; public IndexedEnumerable(IEnumerable<IndexedItem> items) { _items = items; } public class IndexedItem { public IndexedItem(int index, T value) { Index = index; Value = value; } public T Value { get; private set; } public int Index { get; private set; } } public static IndexedEnumerable<T> Create(IEnumerable<T> items) { return new IndexedEnumerable<T>(items.Select((item, index) => new IndexedItem(index, item))); } public IEnumerator<IndexedItem> GetEnumerator() { return _items.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } 

其中给出了一个用例:

 var items = new[] {1, 2, 3}; var indexedItems = items.ToIndexed(); foreach (var item in indexedItems) { Console.WriteLine("items[{0}] = {1}", item.Index, item.Value); }