获得从枚举下一个N个元素 [英] Get next N elements from enumerable
问题描述
上下文:C#3.0的.Net 3.5
假设我有一个生成随机数的方法(永远):
Context: C# 3.0, .Net 3.5
Suppose I have a method that generates random numbers (forever):
private static IEnumerable<int> RandomNumberGenerator() {
while (true) yield return GenerateRandomNumber(0, 100);
}
我需要组合这些数字在10组,所以我想是这样的:
I need to group those numbers in groups of 10, so I would like something like:
foreach (IEnumerable<int> group in RandomNumberGenerator().Slice(10)) {
Assert.That(group.Count() == 10);
}
我已经定义切片的方法,但我觉得应该有一个已定义。这里是我的切片方法,仅供参考:
I have defined Slice method, but I feel there should be one already defined. Here is my Slice method, just for reference:
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的?
Question: is there an easier way to accomplish what I'm trying to do? Perhaps Linq?
注:上面的例子是一个简化的,在我的程序我有,它可以扫描给定矩阵在非线性方式的Iterator
Note: above example is a simplification, in my program I have an Iterator that scans given matrix in a non-linear fashion.
编辑:为什么跳过
+ 以
也是白搭。
Why Skip
+Take
is no good.
有效我要的是:
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号和10打破这些4组的解决方案。
without the overhead of regenerating number (10+20+30+40) times. I need a solution that will generate exactly 40 numbers and break those in 4 groups by 10.
推荐答案
我做了类似的事情。但我想它是简单的:
I have done something similar. But I would like it to be simpler:
//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);
}
}
}
我觉得你是有缺陷的。你返回相同的数组,你所有的块/切片所以才有了最后一个块/片你把本来正确的数据。
I think yours are flawed. You return the same array for all your chunks/slices so only the last chunk/slice you take would have the correct data.
增加:阵列版本:
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)。正如指出的那样,它不会对无限序列的工作,将是一个很大的比其它的要慢:
Addition: Linq version (not C# 2.0). As pointed out, it will not work on infinite sequences and will be a great deal slower than the alternatives:
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());
}
这篇关于获得从枚举下一个N个元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!