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

它给出了我所期待的答案。

任何帮助都会很有帮助。

谢谢。

使用Where子句的C#结果序列

这是您最终得到的查询:

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、35整除的数字",那么您需要做不同的操作。

你的代码会过滤每一步,只让任何合适的数字进入下一步,所以每个数字都会过滤,但你想要相反的数字,如果其中任何一个说可以,那么你想要这个数字。

要获得表达式,这将是代码:

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