C#记录02-3 控制器相关知识点2
1、多重分组列表生成逻辑
这里来拆解一条较为复杂的多重列表生成哈,先放处理后的整句代码。
var List = list.Where(p => p.P.mark3 != null)
.GroupBy(p => new { p.M.mark1, p.M.mark2,
p.P.mark3 })
.Select(p => new { K = p.Key, data = p.ToList() })
.ToList();
1.1、Where字段进行数据筛选
作用是过滤掉P.mark3里 为 null的记录,确保分组键的有效性。
1.2、GroupBy分组逻辑
由mark1、mark2、mark3三个字段组成的分组键;如果某两条数据中这三个字段完全相同,则会被分到同一组内。
举例:数据1:mark1=1;mark2=2;mark3=3;
数据2:mark1=1;mark2=2;mark3=3;
数据3:mark1=4;mark2=2;mark3=3;
分组结果: K={1,2,3};data=【数据1、数据2】;
K={4,2,3};data=【数据3】;
1.3、Select结果转换
此处的 K 对应的就是上述处理的分组键(mark1+mark2+mark3);data则对应上述分组后该组的所有数据列表。
举例:[
{
"K": { "mark1": 1, "mark2": 2, "mark3": 3 },
"data": [ { ...数据1... }, { ...数据2... } ]
},
{
"K": { "mark1": 4, "mark2": 2, "mark3": 3 },
"data": [ { ...数据3... } ]
}
]
1.4、 Tolist执行查询
作用是立即执行查询,并将分组结果转换为 List,前面文章有提到不多累述。
1.5、小结
源代码里仅对分组键其中之一有空值检查,如果其他两个也有空值则容易报错,除了源代码里的写法之外,也可以试着用空运算符?进行空值检查。
举例:
var List = list.Where(p => p.P?.mark3 != null)
.GroupBy(p => new { p.M?.mark1, p.M?.mark2,
p.P?.mark3 })
2、处理分组后的数据
老规矩,先上脱敏处理后的整片代码。
foreach (var plan in List)
{
Class1 X = new Class1();
X.Month = begin;// 设置月份(begin为之前定义的起始时间)
if (dict1.TryGetValue((double)plan.Key.mark3, out mark3ID quip))
{
X.Name1 = quip.Name;
X.Code1 = quip.Code;
}
if (dict2.TryGetValue((double)plan.Key.mark1, out mark1ID vat))
{
X.Name2 = vat.VatName;
X.Code2 = vat.VatCode;
}
if (dict3.TryGetValue((double)plan.Key.mark2, out mark2ID ana))
{
X.Name3 = ana.ProName;
}
2.1、初始化对象和声明类型
Class1 X = new Class1();
X.Month = begin;// 设置月份(begin为之前定义的起始时间)
这里的作用其实就是为每个分组创建一个新的统计结果对象,并记录时间范围。
这里通过 new关键字调用构造函数,创建一个新的 Class1对象,对象的所有字段/属性被赋予默认值(如 string为 null,int为 0)。
为什么X定义前面要放一个Class1而不是var呢,这个我查了下说是显示类型声明和隐式类型推断的区别,显示类型声明一般用于团队协作的场景,减少类型推断的歧义。
2.2、查找与赋值
if (dict1.TryGetValue((double)plan.Key.mark3, out mark3ID quip))
针对这一句其实咋一看挺复杂,目的就是尝试从字典dict1查找键 (double)plan.Key.mark3。
找得到的话就放回true进入if,并将对应的值赋给 quip(out参数);
如果找不着就会返回false跳过if,quip取得默认值。
关于这个 out 好像也可以讲讲,在C#里,out用于指示参数按引用传递,且方法内部 必须 为 out参数赋值,out的好用之处在于它可以返回额外的信息不止于值。
后面还好多,不管先写到这发了。
更多推荐
所有评论(0)