与索引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值。 它将有两个属性
- 价值:与集合中的原始价值
- 索引:与索引内的集合
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){…}