为什么这不会产生幸运数字?
Why doesn't this generate the lucky numbers?
我正在尝试编写一个生成 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;
遍历它们并return下一个幸运数字:
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,但第一次迭代是敲击每个 second 个数字。所以你必须拿 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
个幸运数字。
我正在尝试编写一个生成 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;
遍历它们并return下一个幸运数字:
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,但第一次迭代是敲击每个 second 个数字。所以你必须拿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
个幸运数字。