跳过C#循环列表中的元素

时间:2015-01-18 15:57:49

标签: c# linq extension-methods ienumerable

我要创建一个扩展方法jump<T>,它采用任意序列s,返回一个无限序列,其元素以循环方式访问并跳过n个元素。所以,如果step == 0,则返回所有序列(无限次),如果step == 1,让我们以区间[0-10]中的所有数字为例,将返回0,2,4, 6,8,10,1,3,5 ecc。如果步骤== 2,那么结果将是0,3,6,9,1,4,7,10。 显然这只是一个有序的int列表的例子,我需要用一个通用的T元素序列来做。

我如何实现这一目标?

为了测试它,我创建了一个nunit测试,如下所示:

  [Test]
        public void Jumping_validArg_IsOk()
    {

        var start = new[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
            .Jumping(3)
            .ToList()//remove this to make it work
            .Take(4);
        var expected = new[] {1, 5, 9, 2};
       CollectionAssert.AreEquivalent(start, expected);
    }

但似乎永远不会结束,它会抛出System.OutOfMemoryException

解决方案: 我修改了一点我选择的最佳答案,以这种方式使它更通用:

        public static IEnumerable<T> Jump<T>(this IEnumerable<T> sequence, int step)
        {
            var pos = 0;
            var list = sequence.ToList();
            while (true)
            {
                yield return list[pos];
                pos = (pos + step + 1) % list.Count;
            }
        }

这样它应该适用于所有IEnumerable。我在测试中添加了评论,以显示要删除的内容以使其正常工作。我希望这一切都是正确的。

1 个答案:

答案 0 :(得分:2)

您可以使用yield return语句轻松实现此目的:

public static IEnumerable<T> Jump<T>(this IList<T> data, int step) {
    int pos = 0;
    while(true) {
        yield return data[pos];
        pos = (pos + step) % data.Count;
    }
}