[英]C# - TakeWhile and SkipWhile not returning?
I have a class RekenReeks which returns numbers starting from 2, multiplied by 2. So {2,4,8,16,32,64} 我有一个RekenReeks类,它返回从2开始的数字,乘以2.所以{2,4,8,16,32,64}
Now I learned about the TakeWhile and SkipWhile methods as well as LINQ. 现在我了解了TakeWhile和SkipWhile方法以及LINQ。
So I have created 3 variables which should store exactly the same but my Console.WriteLine
only prints selection1 and not 2 and 3. 所以我创建了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();
}
}
}
Your sequence is unlimited (theoretically). 你的序列是无限的(理论上)。 You assume too much.
你假设太多了。 The functionality of your program cannot possibly know that your sequence is strictly monotonic increasing.
程序的功能不可能知道您的序列严格单调增加。
var selection = from i in reeks
where i > 10
&& i < 1000
select i;
This will never stop. 这永远不会停止。 Because the
where
will always pull the next value, it does not know it's condition will be satisfied, it always has to check the next value. 因为
where
总是会拉的下一个值,它不知道它的条件将得到满足, 它都将检查下一个值。
var selection2 = reeks.TakeWhile(n => n < 1000 && n > 10);
This will take values, while they are between 11 and 999. As your sequence starts with 2, it will stop right on the first value. 这将取值,而它们在11到999之间。当序列以2开头时,它将在第一个值上停止。
var selection3 = reeks.SkipWhile(n => n > 1000 && n < 10);
This will skip values while they are between 11 and 999. As the first is 2, it will skip none and therefore yield all . 这将在11到999之间跳过值。由于第一个是2,它将跳过无,因此产生全部 。
Both TakeWhile()
and SkipWhile()
start from very beginning of the sequence and stop taking/skipping when condition doesn't meet. TakeWhile()
和SkipWhile()
从序列的最开始开始,当条件不满足时停止进行/跳过。
// I've redesigned your ReekenReeks
// [2, 4, 8, 16, 32, 64, ..., 2**30]
var reeks = Enumerable
.Range(1, 30)
.Select(index => 1 << index);
For instance, if you put 例如,如果你放
var selection2 = reeks
.TakeWhile(n => n < 1000 && n > 10);
since the 1st item of the reeks
is 2
the condition n < 1000 && n > 10
doesn't meet TakeWhile
stops and returns an empty sequence. 由于的第一项
reeks
是2
的条件n < 1000 && n > 10
不符合TakeWhile
停止并返回一个空的序列。 The right implemenation is 正确的实施是
var selection2 = reeks
.SkipWhile(n => n <= 10)
.TakeWhile(n => n < 1000);
If you want to cut off values from the middle of the sequence ( selection3
) you have to use Where
: 如果要从序列中间切除值(
selection3
),则必须使用Where
:
var selection3 = reeks
.Where(n => !(n > 1000 && n < 10)); // cut theses items off
Be careful when printing out an infinine sequence, .Take()
is a good choice here: 打印出无限序列时要小心.Take
.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;
There's no reason for this to ever end. 这没有理由永远结束。 When
i
is 1024 it won't be yielded, but it will still check then if 2048
is less than 1000
, or 4096
is less than 1000
, or 8192
is less than 1000
and so on forever (eventually either overflow exception happens or n
wraps around to 0
which then keeps being set to 0 * 2
which is still 0
). 当
i
是1024时它将不会被产生,但它仍将检查然后2048
是否小于1000
,或4096
小于1000
,或8192
小于1000
等等(最终发生溢出异常或n
包裹)大约为0
,然后保持设置为0 * 2
,仍为0
)。
reeks.TakeWhile(n => n < 1000 && n > 10)
The first value tried is 2
. 尝试的第一个值是
2
。 This does not satisfy the predicate n < 1000 && n > 10
because it is not true that 2 > 10
. 这不满足谓词
n < 1000 && n > 10
因为2 > 10
不是这样。 Therefore the taking stops. 因此停止了。
reeks.SkipWhile(n => n > 1000 && n < 10)
There is no value of n
for which n > 1000 && n < 10
. 没有
n
值, n > 1000 && n < 10
。 Therefore this is the same as having no SkipWhile
at all. 因此,这与没有
SkipWhile
完全相同。
It seems like what you want is: 看起来你想要的是:
reeks.SkipWhile(n => n >= 1000 || n <= 10).TakeWhile(n => n < 1000 && n > 10)
Which skips until the first number that meets the criteria is found, then takes all that meet it until the first that does not. 在找到满足条件的第一个数字之前会跳过,然后将所有符合条件的数字跳到第一个不符合条件的数字。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.