使用LINQ生成数字序列

tan*_*ius 38 c# linq

我尝试编写一个LINQ语句,它返回所有可能的数字组合(我需要这个测试,我的灵感来自Eric Lippert的这篇文章).我调用的方法原型如下:

IEnumerable<Collection<int>> AllSequences( int start, int end, int size );
Run Code Online (Sandbox Code Playgroud)

规则是:

  • 所有返回的集合的长度为 size
  • 集合中的数字值必须增加
  • 应该使用start和之间的每个数字end

所以调用AllSequences( 1, 5, 3 )应该会产生10个集合,每个集合大小为3:

1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4 
2 3 5
2 4 5 
3 4 5
Run Code Online (Sandbox Code Playgroud)

现在,不知怎的,我真的很想看到纯粹的LINQ解决方案.我可以自己编写非LINQ解决方案,所以请不要在没有LINQ的情况下投入解决方案.
到目前为止,我的尝试已经结束,我必须加入一个数字与我的方法的递归调用的结果 - 如下所示:

return from i in Enumerable.Range( start, end - size + 1 )
       select BuildCollection(i, AllSequences( i, end, size -1));
Run Code Online (Sandbox Code Playgroud)

但我无法管理它BuildCollection()在LINQ基础上实现- 甚至跳过此方法调用.你能帮帮我吗?

小智 52

 Enumerable.Range(1, 12)
           .Select(x => (x - 1) + 1);
Run Code Online (Sandbox Code Playgroud)

  • 不回答问题,但回答谷歌搜索. (5认同)
  • 没有回答这个问题,但对我有用,所以+1 (4认同)
  • 这是做什么的?是不是`.Select`多余了? (2认同)
  • **来自审核队列**:我可以请求您在源代码周围添加一些上下文.仅代码的答案很难理解.如果您可以在帖子中添加更多信息,它将帮助提问者和未来的读者. (2认同)

Fed*_*ede 35

我想我已经知道了.

IEnumerable<List<int>> AllSequences(int start, int end, int size)
{
    if (size == 0)
        return Enumerable.Repeat<List<int>>(new List<int>(), 1);

    return from i in Enumerable.Range(start, end - size - start + 2)
           from seq in AllSequences(i + 1, end, size - 1)
           select new List<int>{i}.Concat(seq).ToList();
}
Run Code Online (Sandbox Code Playgroud)


Nol*_*rin 13

我认为,像下面这样的事情应该可以胜任.

public static IEnumerable<IEnumerable<int>> AllSequences(int start, int end,
    int size)
{
    return size <= 0 ? new[] { new int[0] } :
           from i in Enumerable.Range(start, end - size - start + 2)
           from seq in AllSequences(i + 1, end, size - 1)
           select Enumerable.Concat(new[] { i }, seq);
}
Run Code Online (Sandbox Code Playgroud)

解决方案的关键是复合from子句,这对于处理嵌套的可枚举非常方便.

请注意,我已稍微更改了方法签名IEnumerable<IEnumerable<int>>,因为使用(纯)LINQ时更方便.IEnumerable<ICollection<int>>但是,如果您愿意,可以随时将其轻松转换为最终版本.

如果代码需要任何解释,请告诉我,但我希望LINQ语法能够让它变得相当清楚.

编辑1:修复了错误并提高了简洁性.

编辑2: 因为我很无聊并且没有更好的事情要做(不,不是真的),我想我会编写一个扩展方法来计算给定元素列表的组合,并使用该AllSequences方法.

public static IEnumerable<IEnumerable<T>> Combinations<T>(this IList<T> source,
    int num)
{
    return AllSequences(0, source.Count - 1, num).Select(
        seq => seq.Select(i => source[i]));
}
Run Code Online (Sandbox Code Playgroud)

也许不是最有效的计算组合方式,但肯定是非常紧凑的代码!

  • 你偷了我的雷声!我正在努力解决这个问题= D +1 (3认同)