为什么这不会产生幸运数字?

时间:2016-11-18 07:36:11

标签: c# iteration generator sequences

我正在尝试编写一个生成lucky numbers

的函数
static IEnumerable<int> LuckyNumbers()
{
  IEnumerable<int> luckyNumbers = Enumerable.Range(1, int.MaxValue);
  int counter = 1;
  while (true)
  {
    int number = luckyNumbers.ElementAt(counter++);
    yield return number;
    luckyNumbers = luckyNumbers.Where((_, index) => (index + 1) % number != 0);
  }
}

但这会产生:

2,5,7,11,13,17,21,...

这不是幸运数字。

为什么我的代码不起作用?我想:

  1. 从所有自然数字开始:

    IEnumerable<int> luckyNumbers = Enumerable.Range(1, int.MaxValue);
    int counter = 1;
    
  2. 遍历它们并返回下一个幸运数字:

    while (true)
    {
      int number = luckyNumbers.ElementAt(counter++);
      yield return number;
    
  3. 从序列中删除所有n个数字:

    luckyNumbers = luckyNumbers.Where((_, index) => (index + 1) % number != 0);
    
  4. 我不明白为什么这不符合我的意图。

1 个答案:

答案 0 :(得分:0)

有几个原因导致您的代码无效:

  1. 编程中的集合是零索引的。这就是为什么你生成的第一个数字是2,因为它是带索引1的数字。你应该把counter初始化为0。
  2. 我认为你将计数器初始化为1以避免取消序列中的第1个数字(这将有效地杀死所有数字,因此在给定位置获取元素注定要失败)。问题在于幸运数字的定义:第一个幸运数字是1,第一个迭代是打击每个第二个数字。所以你必须采取Math.Min(number, 2)
  3. 最后,您将得到以下信息:

        static IEnumerable<int> LuckyNumbers()
        {
            IEnumerable<int> luckyNumbers = Enumerable.Range(1, int.MaxValue);
            int counter = 0;
            while (true)
            {
                int number = luckyNumbers.ElementAt(counter++);
                yield return number;
                int moduloCheck = Math.Max(number, 2);
                luckyNumbers = luckyNumbers.Where((_, index) => (index + 1) % moduloCheck != 0);
            }
        }
    

    从性能的角度来看,我认为解决方案对于大数字来说是可怕的,因为你会在ElementAt处反复检查第一个数字。因为where-expression不可索引,所以总是会开始检查几个where条件的每个数字。但好处是您只需将其用作LuckyNumbers().Take(n)即可获得第一个n个幸运数字。