迭代并返回连续n个元素的数组

时间:2011-01-11 17:19:35

标签: c# linq extension-methods ienumerable

在Ruby中,Enumerable上有一个each_cons。它像这样工作

(1..5).each_cons(3) {|n| p n}
  

[1,2,3]
  [2,3,4]
  [3,4,5]

我想在C#中这样做。 LINQ会很好。

以下做了类似的事情,但它循环了一对多,并且它也硬编码只返回两个元素

var ints = new int[] { 1, 2, 3, 4, 5, 6, 7 };
var cons = ints.Select((o, i) =>
            new int[]{ ints[i], i == ints.Length - 1 ? 0 : ints[i + 1] });

如果可以将其创建为原始数组上的迭代器而不必创建大量数组,那将是很好的。

3 个答案:

答案 0 :(得分:9)

尝试以下

var ints = Enumerable.Range(1, 3).Select(x => Enumerable.Range(x, 3));

这将返回具有指定值的IEnumerable<IEnumerable<int>>。您可以在任何点添加.ToArray表达式,如果这是意图(不能判断这是[]在红宝石中的意思)

答案 1 :(得分:6)

您可以创建一种以这种方式实现它的扩展方法:

    public static IEnumerable<IEnumerable<T>> each_cons<T>(this IEnumerable<T> enumerable, int length)
    {
        for (int i = 0; i < enumerable.Count() - length + 1; i++)
        {
            yield return enumerable.Skip(i).Take(length);
        }
    }

消耗它:

var ints = Enumerable.Range(1, 7).each_cons(3);

答案 2 :(得分:0)

这是一个通用的扩展方法,结果证明我的当前用例很复杂,但似乎有效。

static class EnumerableExtension
{
    public static IEnumerable<IEnumerable<T>> EachCons<T>(this IEnumerable<T> sequence, int cons)
    {
        for (IEnumerable<T> head = sequence.Take(cons), tail = sequence.Skip(1);
             head.Count() == cons; head = tail.Take(cons), tail = tail.Skip(1))
             yield return head;
    }
}

改用Jay的实现。它的速度要快得多。我刚刚离开这里,因为在Jay的回答中提到了这一点。