• linq中如何合并多个predicate条件


       最近在做一个webAPI 的时候遇到一个需要合并多个predicate条件的问题,下面就是对题的情况。为了方便交流我对case进行了简化,请先看如下代码:

       

    using System.Collections.Generic;
    using System.Linq;
    
    namespace CombineLinqPredicates
    {
        public class Customer
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public string Url { get; set; }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                var customers = GetCustomers();
    
                var filterCustomers = customers.Where(x => x.Id == 2);
            }
    
            private static IEnumerable<Customer> GetCustomers()
            {
                return new List<Customer>()
                {
                    new Customer(){Id=1,Name="Alibaba",Url= "http://www.taobao.com"},
                    new Customer(){Id=2,Name="Jd",Url= "http://www.jd.com"},
                    new Customer(){Id=3,Name="Tencent",Url= "http://www.qq.com"}
                };
            }
        }
    }

    代码非常简单,一个customer 对象有三个属性,id, name 和 url.  和一个过去customer list的方法 GetCustomers.

    在Main方法中, 我通过  

    var filterCustomers = customers.Where(x => x.Id == 2); 

    获取了所有id = 2 的customer 对象。

     假如现在 where 条件中的 ID 需要从 UI 获取,而且我需要再添加一个 条件,比如url 中包含 jd 字符串如何做呢?

     代码可能变成:

                int? inputCustomerId = null;
                string inputUrl = null;
                var customers = GetCustomers();
                //从UI获取值并填充到 inputCustomerId,inputUrl, 这个过程我们省略。
                var filterCustomers = customers;
                if (inputCustomerId.HasValue) filterCustomers = filterCustomers.Where(x => x.Id == inputCustomerId.Value);
                if (!string.IsNullOrEmpty(inputUrl)) filterCustomers = filterCustomers.Where(x => x.Url.Contains(inputUrl));

    在上面的代码中有两次过滤,为了避免这个问题,提高性能,我们需要合并这两个where 条件。

    首先我们看下where 条件的定义: 

     public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);
    

      他的参数类型是 Func<TSource, bool>型的,因此我么可以定义一个类型如下,然后进行合并,具体代码如下:

                Func<Customer, bool> idFilter = x => inputCustomerId.HasValue && x.Id == inputCustomerId.Value;
                Func<Customer, bool> urlFilter = x => !string.IsNullOrEmpty(inputUrl) && x.Url.Contains(inputUrl);
                Func<Customer, bool> filter = x => true && idFilter(x) && urlFilter(x);
    
                filterCustomers = customers.Where(filter);

    这样处理后,就解决了二次过滤的问题。

  • 相关阅读:
    激光打印机基于主机驱动程序、基于 PCL 驱动程序和 PostScript 驱动程序有何区别?
    转贴:打印机语言PostScript和PCL的比较
    编译器相关配置简介
    Graphics View的体系结构
    解决重装Qt后不能编译Examples的问题
    有符号数和无符号数的区别
    51单片机的外设
    AT89S52单片机P3口解惑
    双向端口设计
    AT89s52单片机的掉电测试
  • 原文地址:https://www.cnblogs.com/slardar1978/p/4203222.html
Copyright © 2020-2023  润新知