网上学习资料一大堆,但假如学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技能提拔。
需要这份系统化的资料的朋友,可以戳这里获取
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感爱好的新人,都欢迎参加我们的的圈子(技能互换、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
/适用于C#版本1/
foreach(ListMultiGroupResult u in UserGroupByOccupationAndGender)
{
Console.WriteLine(u.Occupation + “/” + u.Gender);
foreach (User user in u.UserList)
{
Console.WriteLine(PrintUserObject(user));
}
}
/* 输出结果 */
Teacher/True
{id = 1, name = Zhang Long, age = 38, gender = True, occupation = Teacher}
Student/False
{id = 2, name = Zhang Jin, age = 18, gender = False, occupation = Student}
{id = 10, name = Hu Jin, age = 21, gender = False, occupation = Student}
Teacher/False
{id = 3, name = Zhang Shuai, age = 38, gender = False, occupation = Teacher}
Doctor/False
{id = 4, name = Liu Guangzhi, age = 38, gender = False, occupation = Doctor}
{id = 6, name = Liu Shuai, age = 29, gender = False, occupation = Doctor}
Doctor/True
{id = 5, name = Liu Ziming, age = 38, gender = True, occupation = Doctor}
Builder/True
{id = 7, name = Liu Jin, age = 21, gender = True, occupation = Builder}
{id = 8, name = Jiang Long, age = 38, gender = True, occupation = Builder}
Student/True
{id = 9, name = Hu Ziming, age = 21, gender = True, occupation = Student}
3、分组并对各组进行盘算
来看一个SQL中常用的场景例子:
/* SQL里的表达: 按照用户职业分组,查出每个分组的人数及各组的年岁最大值、最小值、平均值和总和 */
SELECT occupation,COUNT(id),MAX(age),MIN(age),AVG(age),SUM(age) FROM USER GROUP BY occupation;
/* C#版本1 */
class AgeGroupResult
{
public string Key { get; set; }
public int MaxAge { get; set; }
public int MinAge { get; set; }
public double AvgAge { get; set; }
public int SumAge { get; set; }
}
IEnumerable userList
= from u in list
group u by u.occupation into n
select new AgeGroupResult()
{
Key = n.Key, //这个Key是occupation
MaxAge = n.Max(r => r.age),
MinAge = n.Min(r => r.age),
AvgAge = n.Average(r => r.age),
SumAge = n.Sum(r => r.age),
};
/* 遍历 输出 */
/适用于C#版本1/
foreach (AgeGroupResult u in userList)
{
Console.WriteLine(PrintAgeGroupObject(u));
}
/* 输出结果 */
{Key = Teacher, MaxAge = 38, MinAge = 38, AvgAge = 38, SumAge = 76}
{Key = Student, MaxAge = 21, MinAge = 18, AvgAge = 20, SumAge = 60}
{Key = Doctor, MaxAge = 38, MinAge = 29, AvgAge = 35, SumAge = 105}
{Key = Builder, MaxAge = 38, MinAge = 21, AvgAge = 29.5, SumAge = 59}
四、多表查询
在学习之前,我们要做一些准备工作,我们需要创建User对象和包罗User对象的聚集,创建Salary对象和包罗Salary对象的聚集,作为后面查询和输出的数据源,拜见这篇文章C#进阶之LINQ表达式总结完成准备工作。
数据源1:
数据源2:
1、交集 Intersect
犹如数学中中的交集,聚集[1,2,3]和聚集[2,3,4]的交集是[2,3],Linq的交集是两种相同结果范例结果集的重合部分。
比如下面这个例子:
/* SQL里的表达: 求25岁以上且薪水凌驾17000的用户姓名、职业*/
SELECT name,occupation FROM User WHERE age > 25; /先查询25岁以上的用户姓名、职业/
INTERSECT
SELECT name,occupation FROM Salary WHERE salary > 17000; /再查询薪水凌驾17000的用户姓名、职业/
/* 在比力两个对象元素之前,我们先重写一个比力对象*/
class CompareUser : IEqualityComparer
{
public bool Equals(User x, User y)
{
if (x.name == y.name && x.occupation.ToLower() == y.occupation.ToLower())
return true;
return false;
}
public int GetHashCode(User obj)
{
return (obj.name+obj.occupation).Length;
}
}
/查询年岁大于25的用户聚集,投影存储他们的姓名和职业/
List user_list = list.Where(u => u.age > 25)
.Select(g => new User(){
name = g.name,
occupation = g.occupation
}).ToList();
/查询薪水大于17000的用户聚集,投影存储他们的姓名和职业/
List salary_list = salaryList.Where(u => u.salary > 17000)
.Select(g => new User(){
name = g.name,
occupation = g.occupation
}).ToList();
/取上面两个聚集的交集为结果集/
List result_list = user_list.Intersect(salary_list, new CompareUser()).ToList();
/* 遍历 输出 /
foreach (User user in user_list)
{
Console.WriteLine(PrintUserObject(user));
}
foreach (User user in salary_list)
{
Console.WriteLine(PrintUserObject(user));
}
foreach (User user in result_list)
{
Console.WriteLine(PrintUserObject(user));
}
/ 输出结果 /
/ 年岁大于25的用户聚集 /
{id = 0, name = Zhang Long, age = 0, gender = False, occupation = Teacher}
{id = 0, name = Zhang Shuai, age = 0, gender = False, occupation = Teacher}
{id = 0, name = Liu Guangzhi, age = 0, gender = False, occupation = Doctor}
{id = 0, name = Liu Ziming, age = 0, gender = False, occupation = Doctor}
{id = 0, name = Liu Shuai, age = 0, gender = False, occupation = Doctor}
{id = 0, name = Jiang Long, age = 0, gender = False, occupation = Builder}
/ 薪水高于17000的用户聚集 /
{id = 0, name = Liu Shuai, age = 0, gender = False, occupation = Doctor}
/ 交集结果集 */
{id = 0, name = Liu Shuai, age = 0, gender = False, occupation = Doctor}
2、并集 Union
犹如数学中中的并集,聚集[1,2,3]和聚集[2,3,4]的交集是[1,2,3,4],Linq的并集是两种相同结果范例结果集的合并聚集。
比如下面这个例子:
/* SQL里的表达: 求25岁以上和薪水少于8000的用户姓名、职业*/
SELECT name,occupation FROM User WHERE age > 25; /先查询25岁以上的用户姓名、职业/
UNION
SELECT name,occupation FROM Salary WHERE salary < 8000; /再查询薪水少于8000的用户姓名、职业/
/同样需要上面求交集时的比力对象/
/查询年岁大于25的用户聚集,投影存储他们的姓名和职业/
List user_list = list.Where(u => u.age > 25)
.Select(g => new User(){
name = g.name,
occupation = g.occupation
}).ToList();
/查询薪水少于8000的用户聚集,投影存储他们的姓名和职业/
List salary_list = salaryList.Where(u => u.salary < 8000)
.Select(g => new User(){
name = g.name,
occupation = g.occupation
}).ToList();
/取上面两个聚集的交集为结果集/
List result_list = user_list.Union(salary_list, new CompareUser()).ToList();
/* 遍历 输出 /
foreach (User user in user_list)
{
Console.WriteLine(PrintUserObject(user));
}
foreach (User user in salary_list)
{
Console.WriteLine(PrintUserObject(user));
}
foreach (User user in result_list)
{
Console.WriteLine(PrintUserObject(user));
}
/ 输出结果 /
/ 年岁大于25的用户聚集 /
{id = 0, name = Zhang Long, age = 0, gender = False, occupation = Teacher}
{id = 0, name = Zhang Shuai, age = 0, gender = False, occupation = Teacher}
{id = 0, name = Liu Guangzhi, age = 0, gender = False, occupation = Doctor}
{id = 0, name = Liu Ziming, age = 0, gender = False, occupation = Doctor}
{id = 0, name = Liu Shuai, age = 0, gender = False, occupation = Doctor}
{id = 0, name = Jiang Long, age = 0, gender = False, occupation = Builder}
/ 薪水少于8000的用户聚集 /
{id = 0, name = Zhang Long, age = 0, gender = False, occupation = Teacher}
{id = 0, name = Zhang Jin, age = 0, gender = False, occupation = Student}
{id = 0, name = Liu Jin, age = 0, gender = False, occupation = Builder}
{id = 0, name = Hu Ziming, age = 0, gender = False, occupation = Student}
{id = 0, name = Hu Jin, age = 0, gender = False, occupation = Student}
/ 并集结果集 */
{id = 0, name = Zhang Long, age = 0, gender = False, occupation = Teacher}
{id = 0, name = Zhang Shuai, age = 0, gender = False, occupation = Teacher}
{id = 0, name = Liu Guangzhi, age = 0, gender = False, occupation = Doctor}
{id = 0, name = Liu Ziming, age = 0, gender = False, occupation = Doctor}
{id = 0, name = Liu Shuai, age = 0, gender = False, occupation = Doctor}
{id = 0, name = Jiang Long, age = 0, gender = False, occupation = Builder}
{id = 0, name = Zhang Jin, age = 0, gender = False, occupation = Student}
{id = 0, name = Liu Jin, age = 0, gender = False, occupation = Builder}
{id = 0, name = Hu Ziming, age = 0, gender = False, occupation = Student}
{id = 0, name = Hu Jin, age = 0, gender = False, occupation = Student}
3、全集 Concat
不同于并集(Union)去除了两个聚集重复的元素,Concat保留重复的元素。
比如,{1,2,3}和{3,4,5}的Union结果是{1,2,3,4,5},而Concat的结果是{1,2,3,3,4,5}。
4、差集 Except
犹如数学中中的差集,聚集[1,2,3]和聚集[2,3]的交集是[1],代码和交并集类似。
/C#写法/
List result_list = big_list.Except(small_list).ToList()
5、去重 Distinct
犹如数学中中的去重,聚集[1,2,3]和聚集[2,3,4]的去重集是[1],即从聚集[1,2,3]中剔除聚集[2,3,4]中出现的聚集[1,2,3]中的元素,[1,2,3]中剔除[2,3],故结果集是[1]。代码和交并集类似。
/C#写法/
List result_list = big_list.Distinct(small_list).ToList()
6、合并 Zip
Zip函数可以按照元素顺序合并两个聚集的元素构成一个装纳新元素的聚集,聚集[1,2,3]和聚集[2,3,4],可以合并成[12,23,34]这种字符串拼接的聚集,也可以合并成[{1,2},{2,3},{3,4}]这种新的匿名对象聚集。
/C#写法/
//合并为字符串拼接的新字符串聚集
IEnumerable unionList = list.Zip(salaryList, (i1, i2) => i1.name + ", " + i2.occupation);
//合并为新的匿名对象聚集
var unionList = list.Zip(salaryList, (i1, i2) => new { n = i1.name, m = i2.occupation });
五、Join毗连查询
数据源1:
数据源2:
1、Join毗连查询分类
SQL中常见的毗连查询有:
- left join : 左毗连,返回左表中所有的记录以及右表中毗连字段相称的记录。
- right join : 右毗连,返回右表中所有的记录以及左表中毗连字段相称的记录。
- inner join : 内毗连,又叫等值毗连,只返回两个表中毗连字段相称的行。
- full join : 外毗连,返回两个表中的行:left join + right join。
- cross join : 结果是笛卡尔积,就是第一个表的行数乘以第二个表的行数。
Linq只有Join这个函数。
Linq中的Join毗连查询是通过变动关联表和被关联表的顺序来转换左右毗连的方向,通过调解Where和On等条件筛选函数的位置,来改变逻辑,实现更复杂的内毗连全毗连等功能。
同样,Linq的join方法也有两种写法:
/* C#写法1 <Linq写法>*/
IEnumerable SalaryList =
from u in list
join s in salaryList
on u.id equals s.user_id
select s;
/C#写法2 <Lambda写法>/
IEnumerable SalaryList = list
.Join(
inner: salaryList, /inner: 可以省略/
outerKeySelector: u => u.id, /outerKeySelector: 可以省略/
innerKeySelector: s => s.user_id, /innerKeySelector: 可以省略/
resultSelector: (u, s) => s /resultSelector: 可以省略/
);
2、单条件Join毗连查询
如上面两张表,数据表2的user_id是数据表1的外键,对应数据表1的id,可以通过关联查询把两张表不同的属性通过用户逐一对应。
我们举个例子,利用关联查询查询表1用户信息和对应在表2的薪资信息:
/* SQL里的表达: 查询所有效户的姓名、年岁、职业、性别、是否在职和薪资*/
SELECT u.id, u.name, u.age, u.occupation, u.gender, s.active, s.salary
FROM
User AS u
LEFT JOIN
Salary AS s
ON u.id = s.user_id;
/* C#写法1*/
IEnumerable UserSalaryList =
from u in list
join s in salaryList on u.id equals s.user_id
select new UserSalary
{
id = u.id,
name = u.name,
age = u.age,
occupation = u.occupation,
gender = u.gender,
active = s.active,
salary = s.salary
};
/C#写法2/
IEnumerable UserSalaryList = list
.Join(salaryList, u => u.id, s => s.user_id, (u, s) => new UserSalary
{
id = u.id,
name = u.name,
age = u.age,
occupation = u.occupation,
gender = u.gender,
active = s.active,
salary = s.salary
});
/* 遍历 输出 */
foreach (UserSalary user in UserSalaryList)
{
Console.WriteLine(PrintUserSalaryObject(user));
}
/* 输出结果 */
{id = 1, name = Zhang Long, age = 38, gender = True, occupation = Teacher, active = True, salary = 7800}
{id = 2, name = Zhang Jin, age = 18, gender = False, occupation = Student, active = True, salary = 1500}
{id = 3, name = Zhang Shuai, age = 38, gender = False, occupation = Teacher, active = False, salary = 8800}
{id = 4, name = Liu Guangzhi, age = 38, gender = False, occupation = Doctor, active = True, salary = 12800}
{id = 5, name = Liu Ziming, age = 38, gender = True, occupation = Doctor, active = True, salary = 13600}
{id = 6, name = Liu Shuai, age = 29, gender = False, occupation = Doctor, active = False, salary = 29000}
{id = 7, name = Liu Jin, age = 21, gender = True, occupation = Builder, active = True, salary = 7000}
{id = 8, name = Jiang Long, age = 38, gender = True, occupation = Builder, active = False, salary = 8500}
{id = 9, name = Hu Ziming, age = 21, gender = True, occupation = Student, active = True, salary = 2100}
{id = 10, name = Hu Jin, age = 21, gender = False, occupation = Student, active = True, salary = 1300}
3、多条件Join毗连查询
/* SQL里的表达: 用name和id两个属性关联用户表和薪资表,
查询所有效户中性别是男性且在职的工资信息*/
/* SQL写法1*/
SELECT * FROM User AS u
RIGHT JOIN Salary AS s
ON u.id = s.user_id AND u.name = s.name
AND u.gender = true AND s.active = true;
/* SQL写法2*/
/把筛选条件放到JoinOn后面的Where里可以避免左右毗连
带来的半壁空值的困扰,相当于先关联再筛选/
SELECT * FROM User AS u
RIGHT JOIN Salary AS s
ON u.id = s.user_id AND u.name = s.name
WHERE u.gender = true AND s.active = true;
/* C#写法1*/
/这种写法不保举,结果集会有null,
保举关联后取得数据再做筛选,
即把筛选条件写在Join后的结果集处理里/
IEnumerable JointList = (
from r1 in list
where r1.gender
join r2 in (from r3 in salaryList
where r3.active select r3)
on new
{
ID = r1.id,
r1.name
}
equals new
{
ID = r2.user_id,
r2.name
}
into cls
from c in cls.DefaultIfEmpty()
select c
).ToList();
/C#写法2/
IEnumerable JointList = (
from r1 in list
where r1.gender
join r2 in salaryList
on new
{
ID = r1.id,
r1.name
}
equals new
{
ID = r2.user_id,
r2.name
}
into cls
from c in cls.DefaultIfEmpty()
where c.active
select c
).ToList();
/C#写法3/
IEnumerable JointList = (
from r1 in list
from r2 in salaryList
where
r2.active &&
r1.id == r2.user_id &&
r1.name == r2.name &&
r1.gender
select r2
).ToList();
/C#写法4 <Lambda写法>/
IEnumerable JointList =
list.Where(u => u.gender)
.Join(
salaryList.Where(s => s.active),
u => new { ID = u.id, u.name },
s => new { ID = s.user_id, s.name },
(u, s) => s
);
/C#写法5 <Lambda写法>/
/把方法4对Salary聚集的筛选放在整个毗连查询的后面,
由于gender是User的专有属性,所以gender的筛选不能
放到内容对象为Salary的结果集后面/
IEnumerable JointList =
list.Where(u => u.gender)
.Join(
salaryList,
u => new { ID = u.id, u.name },
s => new { ID = s.user_id, s.name },
(u, s) => s
).Where(s => s.active);
/* 遍历 输出 */
foreach (Salary salary in JointList)
{
if(salary != null)
Console.WriteLine(PrintUserSalaryObject(salary));
}
/* 输出结果 */
{id = 1, name = Zhang Long, occupation = Teacher, active = True, salary = 7800}
{id = 5, name = Liu Ziming, occupation = Doctor, active = True, salary = 13600}
{id = 7, name = Liu Jin, occupation = Builder, active = True, salary = 7000}
{id = 9, name = Hu Ziming, occupation = Student, active = True, salary = 2100}
4、自定义条件Join毗连查询
/Linq自定义条件的Join语法/
public static System.Collections.Generic.IEnumerable Join<TOuter,TInner,TKey,TResult> (
this System.Collections.Generic.IEnumerable outer,
System.Collections.Generic.IEnumerable inner,
Func<TOuter,TKey> outerKeySelector, //结果Tkey需要包罗下列比力器需要的参数
Func<TInner,TKey> innerKeySelector, //结果Tkey需要包罗下列比力器需要的参数
Func<TOuter,TInner,TResult> resultSelector,
System.Collections.Generic.IEqualityComparer comparer);
/尤其注意这里相称比力器的传入参数是TKey范例,
需和outerKeySelector和innerKeySelector的TKey范例保持同等/
举个例子:
根据相同的姓名和职业关联User和Salary信息,查询满足雄性且在职的人的Salary信息。
/新建一个相称比力器CompareUser/
/当两个User对象的name和occupation属性相称时返回true,否则为false/
class CompareUser : IEqualityComparer
{
public bool Equals(User x, User y)
{
if (x.name == y.name && x.occupation.ToLower() == y.occupation.ToLower())
return true;
return false;
}
public int GetHashCode(User obj)
{
return (obj.name + obj.occupation).Length;
}
}
/Linq表达式实现找到符合CompareUser相称比力器的判等要求并且满足多少条件/
IEnumerable JointList = list.Where(u => u.gender)
.Join<User, Salary, User, Salary>(
inner: salaryList,
/由于比力器用到了name和occupation两个属性,所以这里的Selector要包罗这两个有效的属性值/
outerKeySelector: u => new User{ name = u.name, occupation = u.occupation},
innerKeySelector: s => new User{ name = s.name, occupation = s.occupation },
resultSelector: (u, s) => s,
comparer: new CompareUser()
).Where(s => s.active);
/* 遍历 输出 */
foreach (Salary salary in JointList)
{
if(salary != null)
Console.WriteLine(PrintUserSalaryObject(salary));
}
/* 输出结果 */
{id = 1, name = Zhang Long, occupation = Teacher, active = True, salary = 7800}
{id = 5, name = Liu Ziming, occupation = Doctor, active = True, salary = 13600}
{id = 7, name = Liu Jin, occupation = Builder, active = True, salary = 7000}
{id = 9, name = Hu Ziming, occupation = Student, active = True, salary = 2100}
5、GroupJoin查询带分组
GroupJoin和Join的区别在于结果集进行了GroupBy分组,这里直接举一个多条件、自定义的最难例子,由于就是Join语法和GroupBy语法的团结体,不难理解,不多叙述。
/* GroupJoin语法 */
IEnumerable JointList = list.Where(u => u.gender)
.GroupJoin(
inner: salaryList.Where(s => s.active),
outerKeySelector: u => new User { name = u.name, occupation = u.occupation },
innerKeySelector: s => new User { name = s.name, occupation = s.occupation },
resultSelector: (u, s) => new ListMultiGroupResult2 {
Occupation = u.occupation,
Name = u.name,
SalaryList = s.ToList() },
comparer: new CompareUser()
);
/自定义相称比力器CompareUser/
class CompareUser : IEqualityComparer
{
public bool Equals(User x, User y)
{
if (x.name == y.name && x.occupation.ToLower() == y.occupation.ToLower())
return true;
return false;
}
public int GetHashCode(User obj)
{
return (obj.name + obj.occupation).Length;
}
}
/* 遍历 输出 */
foreach (ListMultiGroupResult2 s in JointList)
{
Console.WriteLine(s.Occupation + “/” + s.Name);
foreach (Salary salary in s.SalaryList)
{
Console.WriteLine(PrintSalaryObject(salary));
}
}
/* 输出结果 */
Teacher/Zhang Long
{id = 1, name = Zhang Long, occupation = Teacher, active = True, salary = 7800}
Doctor/Liu Ziming
{id = 5, name = Liu Ziming, occupation = Doctor, active = True, salary = 13600}
Builder/Liu Jin
{id = 7, name = Liu Jin, occupation = Builder, active = True, salary = 7000}
Builder/Jiang Long
Student/Hu Ziming
{id = 9, name = Hu Ziming, occupation = Student, active = True, salary = 2100}
六、投影
投影的过程就是把取得的结果进行处理,可以把结果聚集内的对象只取其中一个或多个元素构成一个新的聚集,生成一个原对象、基本范例、元组或匿名对象的新聚集。
1、投影成原对象
/* C#版本1 /
List userList = (from u in list where u.occupation == “Doctor” select u).ToList();
/ C#版本2 */
List userList = list.Where(p => p.occupation == “Doctor”).ToList();
/* 投影后聚集 */
[{id = 11, name = Zhang San, age = 21, gender = False, occupation = Doctor},
{id = 7, name = Li Si, age = 21, gender = True, occupation = Doctor},
{id = 2, name = Wang Wu, age = 18, gender = False, occupation = Doctor}]
2、投影成基本范例
这里是把原有的User聚集中每个User的name属性提取出来,构成一个全是name的新的聚集,故新聚集为String属性。
/* C#版本1 /
List nameList = (from u in list where u.occupation == “Doctor” select u.name).ToList();
/ C#版本2 */
List nameList = list.Where(p => p.occupation == “Doctor”).Select(x => x.name).ToList();
/* 投影后聚集 */
[“Zhang San”, “Li Si”, “Wang Wu”]
3、投影成元组
/* C#版本1 /
var userList = (from u in list where u.occupation == “Doctor” select ( Name: u.name, Age: u.age )).ToList();
/ C#版本2 */
var userList = list.Where(x => x.occupation == “Doctor”).Select(u => (Name: u.name, Age: u.age)).ToList();
/* 投影后聚集 */
[(“Zhang San”, 21), (“Li Si”, 21), (“Wang Wu”, 18)]
4、投影成匿名对象
/* C#版本1 /
var userList = (from u in list where u.occupation == “Doctor” select new { u.name, u.age }).ToList();
/ C#版本2 */
var userList = list.Where(x => x.occupation == “Doctor”).Select(u => new { u.name, u.age }).ToList();
/* 投影后聚集 */
[{“Zhang San”, 21}, {“Li Si”, 21}, {“Wang Wu”, 18}]
七、对聚集增编削查
Linq是对聚集进行操作,这里列举对聚集增编削查的常用方法。在学习之前,我们要做一些准备工作,我们需要创建User对象和包罗User对象的聚集,创建Salary对象和包罗Salary对象的聚集,作为后面查询和输出的数据源,拜见这篇文章C#进阶之LINQ表达式总结完成准备工作。
数据源1:
数据源2:
1、新增聚集内对象
/* 新增一个恣意属性的用户到聚集 /
/ C#版本1 */
User userAdd = new User() {
id = 11,
name = “Liu Mingxiu”,
age = 22,
gender = false,
occupation = “Doctor”
};
list.Add(userAdd);
/* C#版本2(支持一次添加多个) */
IEnumerable userAddList = new List().Append(userAdd);
list.AddRange(userAddList);
/* 输出结果 */
{id = 1, name = Zhang Long, age = 38, gender = True, occupation = Teacher},
{id = 2, name = Zhang Jin, age = 18, gender = False, occupation = Student},
{id = 3, name = Zhang Shuai, age = 38, gender = False, occupation = Teacher},
{id = 4, name = Liu Guangzhi, age = 38, gender = False, occupation = Doctor},
{id = 5, name = Liu Ziming, age = 38, gender = True, occupation = Doctor},
{id = 6, name = Liu Shuai, age = 29, gender = False, occupation = Doctor},
{id = 7, name = Liu Jin, age = 21, gender = True, occupation = Builder},
{id = 8, name = Jiang Long, age = 38, gender = True, occupation = Builder},
深知大多数步调员,想要提拔技能,通常是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技能停滞不前!
既有得当小白学习的零根本资料,也有得当3年以上经验的小伙伴深入学习提拔的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!
由于文件比力多,这里只是将部分目录截图出来,全套包罗大厂面经、学习笔记、源码讲义、实战项目、大纲门路、解说视频,并且后续会持续更新
需要这份系统化的资料的朋友,可以戳这里获取
name = Zhang Shuai, age = 38, gender = False, occupation = Teacher},
{id = 4, name = Liu Guangzhi, age = 38, gender = False, occupation = Doctor},
{id = 5, name = Liu Ziming, age = 38, gender = True, occupation = Doctor},
{id = 6, name = Liu Shuai, age = 29, gender = False, occupation = Doctor},
{id = 7, name = Liu Jin, age = 21, gender = True, occupation = Builder},
{id = 8, name = Jiang Long, age = 38, gender = True, occupation = Builder},
深知大多数步调员,想要提拔技能,通常是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技能停滞不前!
[外链图片转存中…(img-wsnXU2V8-1715296244415)]
[外链图片转存中…(img-M0i9J4bk-1715296244416)]
既有得当小白学习的零根本资料,也有得当3年以上经验的小伙伴深入学习提拔的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!
由于文件比力多,这里只是将部分目录截图出来,全套包罗大厂面经、学习笔记、源码讲义、实战项目、大纲门路、解说视频,并且后续会持续更新
需要这份系统化的资料的朋友,可以戳这里获取
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |