C# - TakeWhile 和 SkipWhile 不返回?
C# - TakeWhile and SkipWhile not returning?
我有一个 class RekenReeks,其中 returns 数字从 2 开始,乘以 2。所以 {2,4,8,16,32,64}
现在我了解了 TakeWhile 和 SkipWhile 方法以及 LINQ。
所以我创建了 3 个变量,它们应该存储完全相同但我的 Console.WriteLine
只打印 selection1 而不是 2 和 3。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
RekenReeks reeks = new RekenReeks(2, n => n * 2);
var selection = from i in reeks
where i > 10
&& i < 1000
select i;
var selection2 = reeks.TakeWhile(n => n < 1000 && n > 10);
var selection3 = reeks.SkipWhile(n => n > 1000 && n < 10);
foreach (int i in selection)
{
Console.WriteLine("selection1 {0}",i);
}
foreach (int i in selection2)
{
Console.WriteLine("selection2 {0}", i);
}
foreach (int i in selection3)
{
Console.WriteLine("selection3 {0}", i);
}
Console.ReadLine();
}
}
public class RekenReeks : IEnumerable<int>
{
Func<int, int> getNew;
int number;
public RekenReeks(int starton, Func<int, int> getNewThing)
{
getNew = getNewThing;
number = starton;
}
public IEnumerator<int> GetEnumerator()
{
yield return number;
for (; ; )
{
yield return getNew(number);
number = getNew(number);
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
}
你的序列是无限的(理论上)。你假设太多了。您的程序的功能不可能知道您的序列是严格单调递增的。
var selection = from i in reeks
where i > 10
&& i < 1000
select i;
这永远不会停止。因为 where
总是会提取下一个值,它不知道它的条件是否会得到满足,所以它总是 必须 检查下一个值。
var selection2 = reeks.TakeWhile(n => n < 1000 && n > 10);
这将采用介于 11 和 999 之间的值。由于您的序列以 2 开头,它将在第一个值处停止。
var selection3 = reeks.SkipWhile(n => n > 1000 && n < 10);
这将跳过介于 11 和 999 之间的值。由于第一个是 2,它将跳过 none,因此产生 all.
TakeWhile()
和 SkipWhile()
都从序列的最开始开始,当条件不满足时停止 taking/skipping。
// I've redesigned your ReekenReeks
// [2, 4, 8, 16, 32, 64, ..., 2**30]
var reeks = Enumerable
.Range(1, 30)
.Select(index => 1 << index);
例如,如果您输入
var selection2 = reeks
.TakeWhile(n => n < 1000 && n > 10);
由于 reeks
的第一项是 2
条件 n < 1000 && n > 10
不满足 TakeWhile
停止并且 returns 一个 空序列。正确的实现是
var selection2 = reeks
.SkipWhile(n => n <= 10)
.TakeWhile(n => n < 1000);
如果您想从序列 (selection3
) 的 中间 截断值,您必须使用 Where
:
var selection3 = reeks
.Where(n => !(n > 1000 && n < 10)); // cut theses items off
打印出 infinine 序列时要小心,.Take()
是一个不错的选择:
var selection3 = reeks
.Where(n => n > 1000 && n < 10)
.Take(100); // First 100 items in case the sequence is too long
var selection = from i in reeks
where i > 10
&& i < 1000
select i;
没有理由让它永远结束。当 i
为 1024 时它不会产生,但它仍然会检查 2048
是否小于 1000
,或者 4096
是否小于 1000
,或者 8192
小于 1000
等等(最终要么发生溢出异常,要么 n
环绕到 0
然后一直设置为 0 * 2
仍然是 0
).
reeks.TakeWhile(n => n < 1000 && n > 10)
尝试的第一个值是 2
。这不满足谓词 n < 1000 && n > 10
因为 2 > 10
不成立。因此停止服用。
reeks.SkipWhile(n => n > 1000 && n < 10)
n > 1000 && n < 10
没有 n
的值。因此,这与根本没有 SkipWhile
是一样的。
看来你想要的是:
reeks.SkipWhile(n => n >= 1000 || n <= 10).TakeWhile(n => n < 1000 && n > 10)
跳过直到找到满足条件的第一个数字,然后获取所有符合条件的数字,直到找到第一个不符合条件的数字。
我有一个 class RekenReeks,其中 returns 数字从 2 开始,乘以 2。所以 {2,4,8,16,32,64}
现在我了解了 TakeWhile 和 SkipWhile 方法以及 LINQ。
所以我创建了 3 个变量,它们应该存储完全相同但我的 Console.WriteLine
只打印 selection1 而不是 2 和 3。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
RekenReeks reeks = new RekenReeks(2, n => n * 2);
var selection = from i in reeks
where i > 10
&& i < 1000
select i;
var selection2 = reeks.TakeWhile(n => n < 1000 && n > 10);
var selection3 = reeks.SkipWhile(n => n > 1000 && n < 10);
foreach (int i in selection)
{
Console.WriteLine("selection1 {0}",i);
}
foreach (int i in selection2)
{
Console.WriteLine("selection2 {0}", i);
}
foreach (int i in selection3)
{
Console.WriteLine("selection3 {0}", i);
}
Console.ReadLine();
}
}
public class RekenReeks : IEnumerable<int>
{
Func<int, int> getNew;
int number;
public RekenReeks(int starton, Func<int, int> getNewThing)
{
getNew = getNewThing;
number = starton;
}
public IEnumerator<int> GetEnumerator()
{
yield return number;
for (; ; )
{
yield return getNew(number);
number = getNew(number);
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
}
你的序列是无限的(理论上)。你假设太多了。您的程序的功能不可能知道您的序列是严格单调递增的。
var selection = from i in reeks
where i > 10
&& i < 1000
select i;
这永远不会停止。因为 where
总是会提取下一个值,它不知道它的条件是否会得到满足,所以它总是 必须 检查下一个值。
var selection2 = reeks.TakeWhile(n => n < 1000 && n > 10);
这将采用介于 11 和 999 之间的值。由于您的序列以 2 开头,它将在第一个值处停止。
var selection3 = reeks.SkipWhile(n => n > 1000 && n < 10);
这将跳过介于 11 和 999 之间的值。由于第一个是 2,它将跳过 none,因此产生 all.
TakeWhile()
和 SkipWhile()
都从序列的最开始开始,当条件不满足时停止 taking/skipping。
// I've redesigned your ReekenReeks
// [2, 4, 8, 16, 32, 64, ..., 2**30]
var reeks = Enumerable
.Range(1, 30)
.Select(index => 1 << index);
例如,如果您输入
var selection2 = reeks
.TakeWhile(n => n < 1000 && n > 10);
由于 reeks
的第一项是 2
条件 n < 1000 && n > 10
不满足 TakeWhile
停止并且 returns 一个 空序列。正确的实现是
var selection2 = reeks
.SkipWhile(n => n <= 10)
.TakeWhile(n => n < 1000);
如果您想从序列 (selection3
) 的 中间 截断值,您必须使用 Where
:
var selection3 = reeks
.Where(n => !(n > 1000 && n < 10)); // cut theses items off
打印出 infinine 序列时要小心,.Take()
是一个不错的选择:
var selection3 = reeks
.Where(n => n > 1000 && n < 10)
.Take(100); // First 100 items in case the sequence is too long
var selection = from i in reeks
where i > 10
&& i < 1000
select i;
没有理由让它永远结束。当 i
为 1024 时它不会产生,但它仍然会检查 2048
是否小于 1000
,或者 4096
是否小于 1000
,或者 8192
小于 1000
等等(最终要么发生溢出异常,要么 n
环绕到 0
然后一直设置为 0 * 2
仍然是 0
).
reeks.TakeWhile(n => n < 1000 && n > 10)
尝试的第一个值是 2
。这不满足谓词 n < 1000 && n > 10
因为 2 > 10
不成立。因此停止服用。
reeks.SkipWhile(n => n > 1000 && n < 10)
n > 1000 && n < 10
没有 n
的值。因此,这与根本没有 SkipWhile
是一样的。
看来你想要的是:
reeks.SkipWhile(n => n >= 1000 || n <= 10).TakeWhile(n => n < 1000 && n > 10)
跳过直到找到满足条件的第一个数字,然后获取所有符合条件的数字,直到找到第一个不符合条件的数字。