目录
一、基本十招
【总结】
1.获取列表用.where(条件).Tolist()
2.获取实体用FirstOrDefault(条件)
3.如果没有该方法,请先.Tolist(),因为大多数都是列表的方法
class MainClass
{
static List<Person> personList = new List<Person>()
{
new Person(){ Id=1,Name="小明",Age=20,Score=100},
new Person(){ Id=2,Name="小王",Age=40,Score=80},
new Person(){ Id=3,Name="小刘",Age=60,Score=60},
};
static List<Person> personList2 = new List<Person>()
{
new Person(){ Id=4,Name="小测试",Age=12,Score=90},
};
static void Main(string[] args)
{
//一、查找数据
//(1)查找年龄=40的实体列表
var age40List = personList.Where(p => p.Age == 40).ToList();//where是惰性求值,若不加ToList使用时才会实际执行筛选
//(2)查找查找年龄=40的第一条数据的名字,存入字符串(?.表示不为空才点出实体,以防报错)
var age40Name = personList.FirstOrDefault(p => p.Age == 40)?.Name;
//(3)查找ID在ID列表的数据
List<int> listID = new List<int>() { 2, 4 };
var personListInID = personList.Where(x => listID.Contains(x.Id)).ToList();//查询ID=2或4的所有实体
//(4)寻找实体的索引和寻找索引的实体
int index = personList.FindIndex(x => x.Age == 40);//找出Age=40的索引位置
Person p1 = personList[2];//找出索引=2的实体【不推荐】
Person p2 = personList.ElementAtOrDefault(2);//找出索引=2的实体【推荐:找不到返回null】
//2.分页查找(若超出索引,GetRange会报错,skip不会)
var pageList = personList.Skip(1).Take(2);//跳过1条数据取2条数据(即从索引1开始取2条数据)
var rangeList = personList.GetRange(1, 2);//从索引1开始取2条数据
//二、映射数据
// 查找年龄=40的人的姓名列表
var nameList = personList.Where(p => p.Age == 40).Select(p => p.Name).ToList();
// 查找年龄=40的人的[姓名,id]列表
var nameIdList = personList.Where(p => p.Age == 40).Select(p => new { p.Name, p.Id }).ToList();
//三、数据总量和存在性
bool b1 = personList.Any();//列表只要数据存在元素返回true
bool b2 = personList.Any((p) => p.Age < 50);//列表只要一个符合=>返回True (这个和下面这个是一样的功能)
bool b3 = personList.Exists((p) => p.Age < 50);//列表只要一个符合=>返回True
bool b4 = personList.TrueForAll((p) => p.Age < 50);//列表都符合该条件=>返回True(和IEnumerable<T>的All方法是一个意思)
int count = personList.Count((p) => p.Age >= 20);//返回满足条件的条数
//四、排序和颠倒
var orderList1 = personList.OrderBy(p => p.Score).ThenBy(p => p.Age);//先按照Score升序排序,再按照Age升序排序
var orderList2 = personList.OrderByDescending(p => p.Score).ThenBy(p => p.Age);//先按照Score降序排序,再按照Age升序排序
personList.Reverse();//元素顺序反转,不需要赋值,会更改原始列表
//五、聚合函数
// 1. 计算所有人的年龄总和
var sum = personList.Sum(p=>p.Age);
// 2. 计算所有人的平均年龄
var avg = personList.Select(p => p.Age).DefaultIfEmpty().Average();
// 3. 获取所有人中的最大年龄
var max = personList.Select(p => p.Age).DefaultIfEmpty().Max();
// 4. 获取所有人中的最小年龄
var min = personList.Select(p => p.Age).DefaultIfEmpty().Min();
// 5. 获取年龄最大的人(返回的是整个实体对象)
var max_entity = personList.MaxBy(p => p.Age);
// 6. 获取年龄最小的人(返回的是整个实体对象)
var min_entity = personList.MinBy(p => p.Age);
//六、列表添加操作
//(1)两个列表相加,返回给第三个列表(不修改personList列表)
var personList3 = personList.Concat(personList2);
//(2)往personlist里面加入personlist2列表(会直接修改personlist列表)
personList.AddRange(personList2);
//(3)往personlist里面加入person实体
Person person = new Person { Id = 5, Name = "小加入", Age = 16, Score = 92 };
personList.Add(person);
//七、实体提取成字典
//要求:姓名为键 分数为值,存进字典里
Dictionary<string, int> dict = personList.ToDictionary(x => x.Name, x => x.Score);
//八、列表修改操作(都会修改原始列表)
personList.ForEach(x => x.Score = x.Score - 1);//列表所有Score-1
personList.Where(x => x.Score >= 80).ToList().ForEach(x => x.Score = x.Score - 1); //列表成绩大于80的Score-1
personList.Where(x => x.Score >= 80).ToList().ForEach(x =>
{
x.Score -= 1;//列表成绩大于80的Score-1
x.Age += 1;//列表成绩大于80的Age+1
x.Name = "姓名:" + x.Name;//列表成绩大于80的姓名前加上字符串"姓名:"
});
//九、列表删除操作
//(1)根据条件删除第一个符合条件的元素
personList.Remove(personList.FirstOrDefault(x => x.Age == 40));//删除第一个年龄为40的人
//(2)根据条件删除所有符合条件的元素
personList.RemoveAll(x => x.Score < 60); // 删除所有分数小于60的人
//(3)根据索引删除元素
personList.RemoveAt(1); // 删除索引为1的元素
//十、常数列表
var allnumberlisit = Enumerable.Range(1, 80).ToList();//生成一个List<int>,其中从1开始,长度是80 ,即生成的是:1,2,3,…,80
}
}
class Person
{
public int Id;
public string Name;
public int Age;
public int Score;
public override string ToString()
{
return Id + "," + Name + "," + Age + "," + Score;
}
}
【注意】ForEach是没有返回值的,可传入委托(方法)
//无返回值
tableList = tableList.ForEach(x => x.SalePrice =(x.ConsumeHour/8)* x.SalePrice);//错误
tableList.ForEach(x => x.SalePrice =(x.ConsumeHour/8)* x.SalePrice);//正确
//可传入委托
List<SchoolData> list = GetDatas();//模拟查库
list.ForEach(UpdateCreator);
private static void UpdateCreator(SchoolData input)
{
input.Creator = "后端测试";
}
【注意】remove方法:如果没有该实体,也不会报错。(比如list_int=1,2,3 remove 4 也不会报错)
【注意】Select方法,第二入参定位(x代表被遍历的每个元素,index代表索引位置)
public class Data
{
public int intdata { get; set; }
public string strdata { get; set; }
}
static void Main(string[] args)
{
List<Data> data = new List<Data>()
{
new Data { intdata = 1, strdata = "Data 1" },
new Data { intdata = 2, strdata = "Data 2" },
new Data { intdata = 3, strdata = "Data 3" },
new Data { intdata = 4, strdata = "Data 4" },//需筛选其位置
new Data { intdata = 5, strdata = "Data 5" },
new Data { intdata = 6, strdata = "Data 6" },//需筛选其位置
new Data { intdata = 7, strdata = "Data 7" },
new Data { intdata = 8, strdata = "Data 8" },
new Data { intdata = 9, strdata = "Data 9" },
new Data { intdata = 10, strdata = "Data 10" }
};
var r1 = data.Where(x => x.intdata == 4 || x.intdata == 6)
.Select((x, index) => index + 1);//错误写法,只能得出筛选后的索引,即1,2
var r2 = data.Select((list, index) => new { list, index }) // 保留原始索引
.Where(x => x.list.intdata == 4 || x.list.intdata == 6)
.Select(x => x.index + 1); // 使用原始索引,最后结果:4,6
}
【注意】Average、Max、Min方法:加上 DefaultIfEmpty 确保代码健壮性
var avg1 = personList.Average(p => p.Age); //这种不好,数据为空会报错
var avg2 = personList.Select(p => p.Age).Average(); //这种不好,数据为空会报错
var avg3 = personList.Select(p => p.Age).DefaultIfEmpty().Average();//推荐!DefaultIfEmpty 还可以入参一个默认值,例如DefaultIfEmpty(-99)
二、复杂排序
三、集合计算(交并差+父集子集)
这里只提供简单版本,复杂的实体版本请看:C#高级:利用LINQ进行实体列表的集合运算(交集、差集、左外连接)_c# 差集-优快云博客
1.交并差集
// 旧数据(后端存储)
List<string> alist = new List<string> { "a", "b", "c", "d" };//列表a
// 新数据(前端请求)
List<string> blist = new List<string> { "c", "d", "e", "f" };//列表b
// 获取b有且a没有的数据(增加操作,差集)
List<string> toAdd = blist.Except(alist).ToList();//e f
// 获取a有且b没有的数据(删除操作,差集)
List<string> toRemove = alist.Except(blist).ToList();//a b
// 获取 a 和 b 中都共同存在的数据(此处alist blist位置可以互换,交集)
List<string> common = alist.Intersect(blist).ToList();//c d
// 获取 a 和 b 各自的全部元素的总和(并集)
List<string> union = alist.Union(blist).ToList();//a b c d e f
// 获取 a + b 但不包含共有部分的数据(对称差集)
List<string> unique = union.Except(common).ToList();//a b e f
2.父集子集

// 初始数据
List<string> list1 = new List<string> { "apple", "banana", "cherry" };
List<string> list2 = new List<string> { "banana", "cherry" };
List<string> list3 = new List<string> { "apple", "banana", "cherry" };
List<string> list4 = new List<string> { "apple", "banana", "cherry","mike" };
// 01 子集
// 判断list2/list3/list4是否是list1的子集
bool isSubset1 = list2.All(list1.Contains);//true
bool isSubset2 = list3.All(list1.Contains);//true
bool isSubset3 = list4.All(list1.Contains);//false
// 02 真子集
// 判断list2/list3/list4是否是list1的真子集
bool isProperSubset1 = list2.All(list1.Contains) && list1.Count > list2.Count;//true
bool isProperSubset2 = list3.All(list1.Contains) && list1.Count > list3.Count;//false
bool isProperSubset3 = list4.All(list1.Contains) && list1.Count > list4.Count;//false
四、类型的批量转化(字段映射)
1、非引用类型
下面的例子中,用select关键字也是可以的
//1.List<double> => List<string>
datalist.ConvertAll(x => x.ToString()).ToArray()
//2.string => List<char> => List<string>
var list = "123456".ToList().ConvertAll(x=>x.ToString()); //思路一
var list2 = "123456".ToList().Select(x=>x.ToString()); //思路二
2、引用类型
//1.同一实体 列表字段映射(list1=>list2)
List<Student> list2 = new List<Student>(list1);
//2.不同实体
//(1)用一些Nuget包封装的Map方法映射字段【本质是(2)】
//(2)利用自主封装的反射映射方法
//(3)遍历
var destinctlist = new List<TableName>();
foreach (var item in result)
{
var des = new TableName();
des.a=item.a;
des.b=item.b;
des.c=item.c;
des.d=item.d;
des.e=item.e;
destinctlist.Add(des)
}
//(4)Linq的Select(仅在不涉及复杂逻辑代码时推荐)
var distinctList = result.Select(item => new TableName
{
a = item.a,
b = item.b,
c = item.c,
d = item.d,
e = item.e
}).ToList();
3、List<object>转换
【Oftype方法】
//OfType<Student>() 可以安全地筛选出所有你指定的对象(忽略其他对象)不会轻易报错,而调用 Cast<T>(),若其中一个元素转化失败都会报错。
List<object> objects = new List<object> { new Student(), new Student(), new object(),new Teacher(),"666",123,true };
List<Student> students = objects.OfType<Student>().ToList();//输出两个 Student 实例
【as方法】
var list1 = new List<City>() { new City { CityCode = 1, CityName = "测试" } };
var list2 = new object();
list2 = list1;
var list3 = list2 as List<City>;
五、字段提取和字段子项提取
【Demo演示】
Select的意义是提取字段扔进集合,SlectMany的意义是提取字段的子项扔进集合
class Student
{
public string Name { get; set; }
public List<string> Courses { get; set; }
}
class Program
{
static void Main()
{
var students = new List<Student>
{
new Student { Name = "Alice", Courses = new List<string> { "Math", "Science" } },
new Student { Name = "Bob", Courses = new List<string> { "English", "History" } },
new Student { Name = "Charlie", Courses = new List<string> { "Art", "Music" } }
};
//select的意义是提取字段扔进集合,slectmany的意义是提取字段的子项扔进集合
List<string> name_list = students.Select(x => x.Name).ToList();
List<List<string>> course_list_list = students.Select(x => x.Courses).ToList();
List<string> course_list = students.SelectMany(x => x.Courses).ToList();
List<char> name_item_list = students.SelectMany(x => x.Name).ToList();
}
}
再直白点,一般情况下,select提取内容是T,SelectMany提取的内容是List<T>

将结果映射到一个实体中:
datalist.Select(x=> new Entity { StreeName=x.Town,PointName=x.PositionName}).ToList();
六、用Any和All做元素规则判断
string a = "0";
string b = "abc";
string c = null;
List<string> list = new List<string>() { a,b,c};
// 01 All关键字:【全部都满足】该方法才返回True
var result1 = list.All(string.IsNullOrEmpty);// 输出False
// 02 Any关键字:【其中一个满足】该方法就返回True
var result2 = list.Any(string.IsNullOrEmpty);// 输出True
// 03 传入的变量,本质是一个【入参类型为List的子项类型,出参为bool】的委托
Func<string, bool> method = (input) => input?.StartsWith("ab") ?? false;
var result3 = list.Any(method);//输出True
bool areAllNullOrEmpty = new[] { a, b, c }.All(string.IsNullOrEmpty);//如果全部都是(null或空字符串),输出True
八、重复元素 & 去重
//【普通类型】筛选出重复数据
//假如我有一个list<string> 里面有很多数字,用一句代码筛选出重复出现过的数字
var duplicates = list.GroupBy(x => x)
.Where(g => g.Count() > 1) // 没有重复出现过的数字:g.Count() == 1
.Select(g => g.Key)
.ToList();
/*------------------------------------------------------------------*/
//【普通类型】去重
var uniqueList = list.Distinct().ToList();
//【引用类型】去重
//1.使用 GroupBy 去重
var uniqueData = schoolDataList
.GroupBy(d => new { d.ID, d.Time }) // 按 ID 和 Time 分组
.Select(g => g.First()) // 对每个组取第一个元素
.ToList(); // 转换回 List
//2.使用 Distinct 去重【推荐】
var uniqueData = schoolDataList
.DistinctBy(d => new { d.ID, d.Time }) // 根据 ID 和 Time 去重,默认对每个组取第一个元素
.ToList();
九、列表的相互嵌套查询
【推荐】先查一列后筛查,效率高且简单
class Program
{
// 学生类
public class Student
{
public int ID { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
// 老师类
public class Teacher
{
public int ID { get; set; }
public string Name { get; set; }
public int SID { get; set; } // 关联的学生ID
}
static void Main(string[] args)
{
// 创建学生列表
var students = new List<Student>
{
new Student { ID = 1, Name = "Alice", Age = 16 },
new Student { ID = 2, Name = "Bob", Age = 14 },
new Student { ID = 3, Name = "Charlie", Age = 18 },
new Student { ID = 4, Name = "David", Age = 20 }
};
// 创建老师列表
var teachers = new List<Teacher>
{
new Teacher { ID = 1, Name = "Mr. Smith", SID = 1 },
new Teacher { ID = 2, Name = "Ms. Johnson", SID = 2 },
new Teacher { ID = 3, Name = "Dr. Brown", SID = 3 },
new Teacher { ID = 4, Name = "Mrs. White", SID = 4 }
};
//场景:筛选出学生Age>15的老师信息(推荐第一种做法)
//01 先查SID再筛查【写法中等 性能好】【推荐】
var studentSIDs = students.Where(s => s.Age > 15).Select(s => s.ID).ToList();
var result1 = teachers.Where(t => studentSIDs.Contains(t.SID))
.ToList();
//02 嵌套Any【写法简洁 性能差】
var result2 = teachers.Where(t => students.Any(s => s.ID == t.SID && s.Age > 15))
.ToList();
//03 内连接Join【写法较难 性能好】
var result3 = teachers.Join(students,
t => t.SID, // Teacher 的 SID
s => s.ID, // Student 的 ID
(t, s) => new { Teacher = t, Student = s }) // 通过匿名对象返回 Teacher 和 Student
.Where(ts => ts.Student.Age > 15) // 过滤出学生年龄大于 15 的教师
.Select(ts => ts.Teacher) // 只返回 Teacher 对象
.ToList(); // 转换为列表
//04 转换为字典【写法中等 性能好】
Dictionary<int, Student> studentDict = students.ToDictionary(s => s.ID); // 转换为字典
var result4 = teachers.Where(t => studentDict.ContainsKey(t.SID) && studentDict[t.SID].Age > 15)
.ToList();
//05 查询句法【写法中等 性能好】
var result5 = (from t in teachers
join s in students on t.SID equals s.ID
where s.Age > 15
select t).ToList();
Console.ReadLine();
}
}
十、列表拆分(分页)
// 创建学生列表
var students = new List<Student>
{
new Student { ID = 1, Name = "Alice", Age = 16 },
new Student { ID = 2, Name = "Bob", Age = 14 },
new Student { ID = 3, Name = "Charlie", Age = 18 },
new Student { ID = 4, Name = "David", Age = 20 }
};
List<Student[]> chunks = students.Chunk(2).ToList();//每两个实体为一组(列表4条数据,共分得两组,即chunks的长度为2)
Student[] firstGroup = chunks[0];//Alice Bob
该博客介绍了C#中LINQ的常用扩展方法,包括基本十招、复杂排序、集合计算、类型批量转化、字段提取等。如获取列表用.where(条件).Tolist(),获取实体用FirstOrDefault(条件),还提及了ForEach写法、remove方法等注意事项,以及不同场景下的操作技巧。
5万+

被折叠的 条评论
为什么被折叠?



