我正在尝试编写一个生成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,...
这不是幸运数字。
为什么我的代码不起作用?我想:
从所有自然数字开始:
IEnumerable<int> luckyNumbers = Enumerable.Range(1, int.MaxValue);
int counter = 1;
遍历它们并返回下一个幸运数字:
while (true)
{
int number = luckyNumbers.ElementAt(counter++);
yield return number;
从序列中删除所有n
个数字:
luckyNumbers = luckyNumbers.Where((_, index) => (index + 1) % number != 0);
我不明白为什么这不符合我的意图。
答案 0 :(得分:0)
有几个原因导致您的代码无效:
counter
初始化为0。1
以避免取消序列中的第1个数字(这将有效地杀死所有数字,因此在给定位置获取元素注定要失败)。问题在于幸运数字的定义:第一个幸运数字是1,第一个迭代是打击每个第二个数字。所以你必须采取Math.Min(number, 2)
。最后,您将得到以下信息:
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
个幸运数字。