上下文:C#3.0,.Net 3.5
假设我有一个生成随机数(永远)的方法:
假设我有一个生成随机数(永远)的方法:
private static IEnumerable<int> RandomNumberGenerator() { while (true) yield return GenerateRandomNumber(0,100); }
我需要将这些数字分组为10,所以我想要的是:
foreach (IEnumerable<int> group in RandomNumberGenerator().Slice(10)) { Assert.That(group.Count() == 10); }
我已经定义了Slice方法,但我觉得应该有一个已经定义.这是我的Slice方法,仅供参考:
private static IEnumerable<T[]> Slice<T>(IEnumerable<T> enumerable,int size) { var result = new List<T>(size); foreach (var item in enumerable) { result.Add(item); if (result.Count == size) { yield return result.ToArray(); result.Clear(); } } }
问题:是否有更简单的方法来完成我想要做的事情? Linq?
注意:上面的例子是一个简化,在我的程序中,我有一个迭代器以非线性方式扫描给定的矩阵.
编辑:为什么Skip Take是不好的.
我想要的是:
var group1 = RandomNumberGenerator().Skip(0).Take(10); var group2 = RandomNumberGenerator().Skip(10).Take(10); var group3 = RandomNumberGenerator().Skip(20).Take(10); var group4 = RandomNumberGenerator().Skip(30).Take(10);
没有再生数(10 20 30 40)次的开销.我需要一个解决方案,它将产生40个数字,并将其分成4组,每组10个.
解决方法
我做了类似的事情但我希望它更简单:
//Remove "this" if you don't want it to be a extension method public static IEnumerable<IList<T>> Chunks<T>(this IEnumerable<T> xs,int size) { var curr = new List<T>(size); foreach (var x in xs) { curr.Add(x); if (curr.Count == size) { yield return curr; curr = new List<T>(size); } } }
我认为你们有缺陷.您为所有的块/片返回相同的数组,因此只有最后一个块/片将具有正确的数据.
增加:阵列版本:
public static IEnumerable<T[]> Chunks<T>(this IEnumerable<T> xs,int size) { var curr = new T[size]; int i = 0; foreach (var x in xs) { curr[i % size] = x; if (++i % size == 0) { yield return curr; curr = new T[size]; } } }
添加:Linq版本(不是C#2.0).如所指出的,它将无法在无限的序列上工作,并且将比替代方案慢许多:
public static IEnumerable<T[]> Chunks<T>(this IEnumerable<T> xs,int size) { return xs.Select((x,i) => new { x,i }) .GroupBy(xi => xi.i / size,xi => xi.x) .Select(g => g.ToArray()); }