Winform/Csharp中使用Linq的Where条件筛选、Select字段映射(左外连接并设置无匹配时默认值)、OrderBy(排序并自定义排序规则)
场景
Java8新特性-Stream对集合进行操作的常用API:
Java8新特性-Stream对集合进行操作的常用API_streamapi操作集合_霸道流氓气质的博客-CSDN博客
上面讲的是在Java中使用Stream中对集合的常用操作。
在C#中Linq是有对应的类似的api。
完整和详细的用法可自行查阅文档,下面记录使用过程中的一些非常规操作。
注:
博客:
霸道流氓气质的博客_CSDN博客-C#,架构之路,SpringBoot领域博主
实现
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 模糊搜索):
Winform/Csharp中使用StackExchange.Redis连接Redis存取数据并序列化对象/反序列化(支持redis key 模糊搜索)_霸道流氓气质的博客-CSDN博客
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;
}
}