【问题标题】:LINQ - Where clause with Boolean methodLINQ - 带有布尔方法的 Where 子句
【发布时间】:2019-06-26 07:02:18
【问题描述】:

我有以下课程。我的目标是根据 productTypeField 和 downloadSpeedField 过滤组件。我有一个列表lstFilteredComps,我想在其中添加下载速度小于或等于 5 的 INTERNET productType 组件,前提是存在大于 5 的组件。如果所有组件都小于或等于 downloadSpeed 5,则应添加 downloadSpeed 小于等于 5 的 INTERNET 组件。

 public ct_Component[] Components {
 get {
     return this.componentsField;
 }
 set {
    this.componentsField = value;
 }
    }

public partial class ct_Component
{
    private string descriptionField;
    private string downloadSpeedField;
    private string productTypeField;
}

我尝试了以下代码,但它在所有情况下都会删除下载速度为 5 的组件,我将如何设置条件来检查是否存在大于 5 的下载速度。也就是说,我的代码只有在更高可用时才应该删除组件,或者换句话说,只有在存在超过 5MB 的 downloadSpeed 组件时才应该调用 FilterInternetComponentLessThan5MB

ct_Component[] Components = response;
foreach (ct_Component comp in Components.Where(c => FilterInternetComponentLessThan5MB(c)))
{
    list<ct_Component> lstFilteredComps= //add filtered components;
}

FilterComponentLessThan5MB 方法

private bool FilterComponentLessThan5MB(ct_Component component)
{
    if (component.productType != "INTERNET" || (component.productType == "INTERNET"
        && int.Parse(Regex.Replace(component.downloadSpeed, @"[^\d]", "")) > 5))
    {
        return true;
    }
    else
        return false;
}

我需要一个类似的检查:

foreach (ct_Component comp in Components.Where(Components.any(x=>x.productType == "INTERNET" && int.Parse(Regex.Replace(x.downloadSpeed, @"[^\d]", "")) > 5) ? true :  FilterInternetComponentLessThan5MB(c)))

【问题讨论】:

  • FilterComponentLessThan5MB 如果速度 > 5 则返回 true,所以它确实是 speedGreaterThan5Components.where(speedGreaterThan5) 返回速度 > 5 的那些而不是删除它。
  • 是的。我的目标是在检查 foreach (ct_Component comp in Components.Where(Components.any(x=&gt;x.productType == "INTERNET" &amp;&amp; int.Parse(Regex.Replace(x.downloadSpeed, @"[^\d]", "")) &gt; 5) ? true : c =&gt; FilterInternetComponentLessThan5MB(c))) 之类的内容后致电 FilterComponentLessThan5MB

标签: c# linq boolean where


【解决方案1】:

给定几个谓词函数:

bool FilterNotInternetComponentOrOver5Mb(ct_Component component) =>
    (component.productTypeField != "INTERNET") ||
    (int.Parse(Regex.Replace(component.downloadSpeedField, @"[^\d]", "")) > 5);

bool FilterInternetComponentOver5Mb(ct_Component component) =>
    component.productTypeField == "INTERNET" &&
        int.Parse(Regex.Replace(component.downloadSpeedField, @"[^\d]", "")) > 5;

您可以使用超过 5 个进行过滤:

var hasOver5 = Components.Any(c => FilterInternetComponentOver5Mb(c));
var lstFilteredComps = Components.Where(c => !hasOver5 || FilterNotInternetComponentOrOver5Mb(c)).ToList();

【讨论】:

    【解决方案2】:

    您可能正在寻找Any 方法,该方法接收一个私有参数,类似于Where,但当集合中的一项为您的谓词评估为真时,它会返回一个布尔值。

    你会得到这样的结果:

    ct_Component[] components = response;
    if (components.Any(c => c.DownloadSpeedNumber > 5))
    {
        var newList = new List<ct_Component>();
        foreach (ct_Component comp in components.Where(FilterInternetComponentLessThan5MB))
        {
            //add filtered components to newList.
        }
    

    其中DownloadSpeedNumber 可以是安全解析现有downloadSpeed 字段的getter 或扩展方法。

    请记住,尽管您将在 Any 方法中遍历数组,所以如果您有一个非常大的数组,您可能会重新考虑使用 Linq,只需使用常规 for 并仅迭代一次。

    【讨论】:

    • 基本上,如果我的条件为真,我想进行方法调用。所以像if(downloadspeed &gt; 5){ foreach (ct_Component comp in components.Where(FilterInternetComponentLessThan5MB) } else { foreach (ct_Component comp in components) }
    • 我相信Any 会帮助您实现这一目标
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-21
    • 1970-01-01
    • 1970-01-01
    • 2012-11-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多