【问题标题】:How to iteratively chain IEnumerable.Where() using a for loop?如何使用 for 循环迭代地链接 IEnumerable.Where()?
【发布时间】:2013-02-02 17:08:30
【问题描述】:

考虑以下代码(虽然有点做作,但它是对现实世界程序的主要简化):

string[] strings = { "ab", "abcd", "abc", "ac", "b", "abcde", "c", "bc" };
string[] filters = { "a", "b", "c" };

// iteratively apply each filter
IEnumerable<string> filteredStrings = strings.ToArray();
foreach (string filter in filters)
{
    // in my real-world program lots of processing and stuff
    // happens here, hence why i need the enclosing foreach loop

    filteredStrings = filteredStrings.Where(s => s.Contains(filter));
}

如您所见,代码迭代地将字符串数组过滤为较小的字符串集。当 for-each 循环结束时,filteredStrings 应该是通过所有过滤器的字符串子集。在这个例子中,这将是:

{ "abcd", "abc", "abcde" }

但是,我得到的输出是:

{ "abcd", "abc", "ac", "abcde", "c", "bc" }

它似乎只过滤掉那些不包含"c" 的字符串,我认为这与它是最后一个过滤器有关。我想我一定不能以正确的方式链接IEnumerable.Where()。这是怎么回事,我怎样才能得到正确的输出?

是的,根据我代码中的 cmets,foreach 循环需要保持完整。

【问题讨论】:

    标签: c# .net linq lambda ienumerable


    【解决方案1】:

    where 委托未按您期望的方式捕获局部变量。变量filter 正在发生变化,它在所有 where 中都使用最后一个结果,因为 Linq 会进行惰性求值。

    将迭代变量复制到本地变量,我相信它会捕获您期望的方式。

    foreach (string filter in filters)
    {
        string localFilter = filter;
        filteredStrings = filteredStrings.Where(s => s.Contains(localFilter));
    }
    

    【讨论】:

    【解决方案2】:

    您正在使用在循环中修改的变量:filter

    创建一个副本:

    foreach (string filter in filters)
    {
        // in my real-world program lots of processing and stuff
        // happens here, hence why i need the enclosing foreach loop
    
        string f = filter;
        filteredStrings = filteredStrings.Where(s => s.Contains(f));
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-10
      • 1970-01-01
      • 2022-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-11
      • 2012-06-27
      相关资源
      最近更新 更多