Winform/Csharp中使用Linq的Where条件筛选、Select字段映射(左外连接并设置无匹配时默认值)、OrderBy(排序并自定义排序规则)

发布时间 2023-03-27 19:27:26作者: 霸道流氓

场景

Java8新特性-Stream对集合进行操作的常用API:

https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/126070657

上面讲的是在Java中使用Stream中对集合的常用操作。

在C#中Linq是有对应的类似的api。

完整和详细的用法可自行查阅文档,下面记录使用过程中的一些非常规操作。

注:

博客:
https://blog.csdn.net/badao_liumang_qizhi

实现

1、Where条件筛选

需要自定义筛选规则,筛选函数需要调用一些三方工具类

                    var keyList = keys.Where(key =>
                       {
                           CarVo car = redis.StringGet<CarVo>(key);
                           PointF point = new PointF(Convert.ToSingle(car.x), Convert.ToSingle(car.y));
                           bool result = GisHelper.isPointInPolygon(point, waitingRoomPoints);
                           return result;
                       }
                    );

比如这里是校验坐标是否在指定区域内,用到的GisHelper是工具类,附工具类实现

        public static bool isPointInPolygon(PointF point ,PointF[] points) {
            GraphicsPath myGraphicsPath = new GraphicsPath();
            Region myRegion = new Region();
            myGraphicsPath.Reset();
            myGraphicsPath.AddPolygon(points);
            myRegion.MakeEmpty();
            myRegion.Union(myGraphicsPath);
            //返回判断点是否在多边形里
            bool result = myRegion.IsVisible(point);
            return result;
        }

2、Select自定义映射规则,实现调用三方方法

模糊搜索到redis中的key的集合,遍历这些key,并映射到key对应的value的集合

                        var carVoList = keyList.Select(key =>
                        {
                            CarVo car = redis.StringGet<CarVo>(key);
                            return car;
                        })

这里用的方法可以参考如下连接redis并存取数据的实现

Winform/Csharp中使用StackExchange.Redis连接Redis存取数据并序列化对象/反序列化(支持redis key 模糊搜索):

https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/129766120

3、OrderBy自定义排序规则,先按照实体的某个属性,再按照另一个属性

                        var carVoList = keyList.Select(key =>
                        {
                            CarVo car = redis.StringGet<CarVo>(key);
                            return car;
                        })//先按照车辆类型排序
                        .OrderBy(a =>
                        {
                            //人车排在最前面
                            if (a.carType.Equals("1"))
                            {
                                return 1;
                            }//指挥车排在第二位
                            else if (a.carType.Equals("3"))
                            {
                                return 2;
                            }//其他车辆排在后面
                            else
                            {
                                return 3;
                            }
                        })//其次按照车牌号字段排序
                          .ThenBy(a => a.carNumber);

比如这里从redis中查询到数据之后,解析到对象,并先根据对象的carType进行排序,

如果类型为1则排在最前面,类型是3,排在第二优先级,其他的类型排在后面,然后

在每个类型中再按照车牌号这个字段排序。

这里的return 1,数字越小优先级越高。

4、Select映射时从一个对象,映射到另一个对象,并新增一个递增的序号字段

                int numberIndex = 1;
                var carVoListWithFixedData = carVoList.Select(carVo =>
                {
                    ResultVo resultVo = new ResultVo
                    {                     
                        number = numberIndex++,
                        carNumber = carVo.carNumber,
                    };
                    resultVo.team = "测试班组";
                    resultVo.direction = "测试方向";
                    return resultVo;
                });

5、linq select 左外连接

包含左边的表的所有行,如果右边表中某行没有匹配,该行内容为空NULL。

                            var query = from carVo in results
                                        join mail in mailList on carVo.carNumber equals mail.car_number into result1
                                        from result in result1.DefaultIfEmpty()
                                        select new ResultVo(carVo.number, carVo.team, carVo.direction, carVo.carNumber, result == default(BusMailList) ? String.Empty : result.driver_name);
                            results = query.ToList();

这里以左边results的结果为主,results有多少条则最终会有多少条。

根据results中每个对象的car_number属性去匹配在mailList中与car_number相等的数据的driver_name属性,如果有则匹配显示,

没有则未空,并将最终结果映射到新的对象。

这里的BusMailList就是mailList的每个对象。

附这里的mailList集合的每个对象BusMailList的类

    public class BusMailList
    {
        public long binding_time { get; set; }
        public string car_number { get; set; }
        public string driver_name { get; set; }
        public string driver_number { get; set; }
        public int id { get; set; }
        public long update_time { get; set; }
    }

以及results集合的每个对象ResultVo的类

    class ResultVo
    {
        [Description("序号")]
        public int number { get; set; }
        [Description("班组")]
        public string team { get; set; }
        [Description("方向")]
        public string direction { get; set; }
        [Description("车号")]
        public string carNumber { get; set; }
        [Description("司机")]
        public string driver { get; set; }


        public ResultVo()
        {

        }

        public ResultVo(int _number, string _carNumber, string _driver)
        {
            number = _number;
            carNumber = _carNumber;
            driver = _driver;
        }
        public ResultVo(int _number, string _carNumber)
        {
            number = _number;
            carNumber = _carNumber;
        }

        public ResultVo( string _carNumber, string _driver)
        {          
            carNumber = _carNumber;
            driver = _driver;
        }

        public ResultVo(int _number,string _team,string _direction,string _carNumber,string _driver)
        {
            number = _number;
            team = _team;
            direction = _direction;
            carNumber = _carNumber;
            driver = _driver;
        }
    }