我正在为自己即将进行的测试做一些工作,发现了一个我无法理解的问题。
int[] div = new int[]{2,3,5};
IEnumerable<int>seq = new int[]{10,15,20,25,30};
for(int i = 0; i<div.Length;i++){
int y = div[i];
seq = seq.Where(s => s%y == 0)
}
seq = seq.ToList();
我认为结果序列是10 15 20 25 30,但实际答案是30。
我尝试自己运行代码,我发现当代码运行for循环时,序列不会重置为原始序列,但它会保留前一个div [i]创建的序列。
例如,当i = 0时,div [0]为2,因此seq选择10,20和30。
当代码进行到i = 1且div [1] = 3时,它用于计算部分的序列仍然是{10,20,30}而不是{10,15,20,25,30}。 / p>
有人可以解释原因吗?
当我像这样移动到for循环的外部时,
int[] div = new int[]{2,3,5};
IEnumerable<int>seq = new int[]{10,15,20,25,30};
int y;
for(int i = 0; i<div.Length;i++){
y = div[i];
seq = seq.Where(s => s%y == 0)
}
seq = seq.ToList();
它给出了我期待的答案。
任何帮助都会非常有用。
谢谢。
答案 0 :(得分:5)
这是您最终得到的结果:
IEnumerable<int> seq = new int[]{10,15,20,25,30};
seq = seq
.Where(s => s%2 == 0)
.Where(s => s%3 == 0)
.Where(s => s%5 == 0);
因此,每个可被2,3整除的数字和 5:
10 is not divisible by 3
15 is not divisible by 2
20 is not divisible by 3
25 is not divisible by 2
30 is divisible by 2 (15), 3 (10), and 5 (6)
所以30是唯一的结果。
现在,如果您想要这样的查询:“我希望seq
中的每个数字都能被2 * 3 或 5”整除,那么您需要做的不同。< / p>
你所拥有的代码将过滤每一步,只允许任何数字适合下一步,所以每个都会过滤,但你想要相反,如果其中任何一个会说它没问题,那你想要号码。
要获取或表达式,这将是代码:
seq.Where(s => div.Any(y => s % y == 0))
这给出了这个结果:
10
15
20
25
30
基本上这个查询说:
seq中的任意数字
s
,对于div中的任意数字y
,其中s
可被y
整除。
关于你的最后一部分,为什么在你将y
移到循环之外后它会发生变化?
好吧,让我们看看实际发生了什么。
当循环中有y
时,如第一个示例所示,对于循环中的每次迭代,您可以将y
视为“新y
”循环迭代“。
因此,您可以考虑生成此查询的代码:
int y1 = 2;
int y2 = 3;
int y3 = 5;
seq = seq
.Where(s => s%y1 == 0)
.Where(s => s%y2 == 0)
.Where(s => s%y3 == 0);
但是,如果你将y
变量移到循环之外,你只有一个y
,你改变了,所以 final 结果就是:
int y = 5; // the last number in the loop
seq = seq
.Where(s => s%y == 0)
.Where(s => s%y == 0)
.Where(s => s%y == 0);
基本上检查每个数字是否可被5整除, 3次。
因此,当你说这给你想要的结果时,它不会做你想要的。或者更确切地说,我假设它没有做你想要的,因为你还没有真正描述你想要代码做什么。
以下是一些解释差异的链接:
答案 1 :(得分:1)
您可以通过添加更多LINQness来简化代码。
如果您要获得的是seq
的值,可以除以{{> 1}}的任何值,您只需执行以下操作:
div
如果您希望seq.Where(s => div.Any(d => s%d == 0));
的值可以除以seq
的值所有,请将div
替换为.Any