我正在尝试编写一个生成 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);
我不明白为什么这不能按我的预期工作。
最佳答案
您的代码不起作用的原因有几个:
- 编程中的集合是零索引的。这就是为什么您生成的第一个数字是 2,因为它是索引为 1 的数字。您应该将
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 表达式不可索引,所以这将始终开始检查每个数字的几个 where 条件。好处是您可以简单地将它用作 LuckyNumbers().Take(n)
以获得第一个 n
幸运数字。
关于c# - 为什么这不会产生幸运数字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40671682/