与索引foreach

有没有Python的enumerate()和Ruby的each_with_index的C#等价?

我为此保留了这个扩展方法:

 public static void Each<T>( this IEnumerable<T> ie, Action<T, int> action ) { var i = 0; foreach ( var e in ie ) action( e, i++ ); } 

像这样使用它:

 var strings = new List<string>(); strings.Each( ( str, n ) => { // hooray } ); 

或者允许类似break的行为:

 public static bool Each<T>( this IEnumerable<T> ie, Func<T, int, bool> action ) { int i = 0; foreach ( T e in ie ) if( !action( e, i++ ) ) return false; return true; } var strings = new List<string>() { "a", "b", "c" }; bool iteratedAll = strings.Each( (str, n) ) => { if( str == "b" ) return false; return true; } ); 

您可以执行以下操作

 foreach ( var it in someCollection.Select((x,i) => new { Value = x, Index=i }) ) { if ( it.Index > SomeNumber) // } 

这将为收集中的每个条目创build一个匿名types值。 它将有两个属性

  1. 价值:与集合中的原始价值
  2. 索引:与索引内的集合

C#foreach没有内置索引。 你需要在foreach循环之外添加一个整数,并且每次增加一个整数。

 int i = -1; foreach (Widget w in widgets) { i++; // do something } 

或者,您可以使用标准for循环,如下所示:

 for (int i = 0; i < widgets.Length; i++) { w = widgets[i]; // do something } 

除了已经给出的LINQ的答案,我有一个“SmartEnumerable”类,它可以让你获得索引和“第一/最后”的性。 在语法方面有些难看,但是您可能会觉得它很有用。

我们可以使用非genericstypes的静态方法来改进types推断,而隐式types也会有所帮助。

我喜欢能够使用foreach,所以我做了一个扩展方法和一个结构:

 public struct EnumeratedInstance<T> { public long cnt; public T item; } public static IEnumerable<EnumeratedInstance<T>> Enumerate<T>(this IEnumerable<T> collection) { long counter = 0; foreach (var item in collection) { yield return new EnumeratedInstance<T> { cnt = counter, item = item }; counter++; } } 

并举例说明:

 foreach (var ii in new string[] { "a", "b", "c" }.Enumerate()) { Console.WriteLine(ii.item + ii.cnt); } 

一个好处是,如果你习惯Python语法,你仍然可以使用它:

 foreach (var ii in Enumerate(new string[] { "a", "b", "c" })) 

我的解决scheme涉及一个简单的Pair类,我为通用实用程序创build,其操作基本上与框架类KeyValuePair相同。 然后我为IEnumerable创build了一个叫做Coordinate的扩展函数(从set theory的术语“ ordinal ”)。

这些函数将为每个项目返回一个包含索引的Pair对象和项目本身。

 public static IEnumerable<Pair<Int32, X>> Ordinate<X>(this IEnumerable<X> lhs) { return lhs.Ordinate(0); } public static IEnumerable<Pair<Int32, X>> Ordinate<X>(this IEnumerable<X> lhs, Int32 initial) { Int32 index = initial - 1; return lhs.Select(x => new Pair<Int32, X>(++index, x)); } 

不,那里没有。

正如其他人所表明的那样,有许多方法可以模拟Ruby的行为。 但是可能有一个实现IEnumerable的types,它不公开一个索引。

这是你的collections

 var values = new[] {6, 2, 8, 45, 9, 3, 0}; 

为此集合制作一系列索引

 var indexes = Enumerable.Range(0, values.Length).ToList(); 

使用范围来迭代索引

 indexes.ForEach(i => values[i] += i); indexes.ForEach(i => Console.Write("[{0}] = {1}", i, values[i])); 

我只是想出了一个有趣的解决scheme:

 public class DepthAware<T> : IEnumerable<T> { private readonly IEnumerable<T> source; public DepthAware(IEnumerable<T> source) { this.source = source; this.Depth = 0; } public int Depth { get; private set; } private IEnumerable<T> GetItems() { foreach (var item in source) { yield return item; ++this.Depth; } } public IEnumerator<T> GetEnumerator() { return GetItems().GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } // Generic type leverage and extension invoking public static class DepthAware { public static DepthAware<T> AsDepthAware<T>(this IEnumerable<T> source) { return new DepthAware<T>(source); } public static DepthAware<T> New<T>(IEnumerable<T> source) { return new DepthAware<T>(source); } } 

用法:

 var chars = new[] {'a', 'b', 'c', 'd', 'e', 'f', 'g'}.AsDepthAware(); foreach (var item in chars) { Console.WriteLine("Char: {0}, depth: {1}", item, chars.Depth); } 

这取决于你正在使用的课程。

Dictionary <(Of <(TKey,TValue>)>)类的示例支持

Dictionary <(Of <(TKey,TValue>)>)generics类提供了从一组键到一组值的映射。

为了枚举的目的,字典中的每一项都被当作一个KeyValuePair <(Of <(TKey,TValue>)>)结构来表示一个值及其关键字。 项目返回的顺序是未定义的。

foreach(KeyValuePair kvp in myDictionary){…}