获得从枚举下一个N个元素 [英] Get next N elements from enumerable

查看:401
本文介绍了获得从枚举下一个N个元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

上下文: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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆