C#结果序列使用Where子句

时间:2015-11-06 08:07:08

标签: c# .net

我正在为自己即将进行的测试做一些工作,发现了一个我无法理解的问题。

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();

它给出了我期待的答案。

任何帮助都会非常有用。

谢谢。

2 个答案:

答案 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