使用Where子句的C#结果序列
本文关键字:结果 Where 子句 使用 | 更新日期: 2023-09-27 18:20:53
我正在为即将到来的测试自己做一些工作,发现这个问题我无法理解。
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}。
有人能解释一下原因吗?
当我像这样把int y移到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();
它给出了我所期待的答案。
任何帮助都会很有帮助。
谢谢。
这是您最终得到的查询:
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整除的数字",那么您需要做不同的操作。
你的代码会过滤每一步,只让任何合适的数字进入下一步,所以每个数字都会过滤,但你想要相反的数字,如果其中任何一个说可以,那么你想要这个数字。
要获得或表达式,这将是代码:
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
,您将对其进行更改,因此最终结果为:
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次。
因此,当你说这会给你想要的结果时,它并没有达到你想要的效果。或者更确切地说,我假设它没有做你想做的事情,因为你实际上还没有描述你想让代码做什么。
以下是解释差异的一些链接:
- 匿名方法(MSDN)
- 在C中的循环中捕获的变量#
- 闭包中变量捕获的详细说明
可以通过添加更多LINQness来简化代码。
如果你想得到的是seq
的值,它可以被div
的任何值所除,你可以简单地做:
seq.Where(s => div.Any(d => s%d == 0));
如果想要seq
的值可以被所有的div
的值所除,请将.Any
替换为.All
。