目录
LINQ语法
过滤数据
投影数据
排序数据
集合操作
聚合操作
分组操作
查找元素
其他操作
常用的集合类
List
LinkedList
HashSet
Dictionary
List:动态数组
LinkedList:双向链表
HashSet:唯一无序集合
Dictionary:键值对集合
场景代码示例
总结
集合类和LINQ是 C# 开发者处理数据的核心工具。本文通过一些常用的api简介数据操作。
LINQ语法
定义
LINQ语法是c#相对其它语言的优势。LINQ (Language Integrated Query) 被定义为一个用于数据查询的功能,它允许开发者通过统一的语法来查询不同类型的数据源,例如集合、数据库等。LINQ 提供了一个集成的查询语言,可以在编译时获得类型检,从而提高代码的可读性和安全性。LINQ 的关键特点包括:
集成查询:LINQ 将查询功能直接集成到 C# 中,而不需要独立的查询语言。这使得查询操作可以像其他编程操作一样嵌入到代码中。
一致的查询模型:无论查询的是集合、数据库、XML 或其他数据源,LINQ 提供了一个一致的查询模型和语法。
强类型和编译时验证:查询条件、投影等都能够在编译时进行类型检查,这减少了运行时错误的风险。
延迟执行:LINQ 查询通常是延迟执行的,只有在实际迭代查询结果时,查询才会被执行。这有助于优化性能,避免不必要的计算。
代码简洁:用简单的方法链实现复杂操作。
通过 LINQ,开发者可以在同一语言中对各种数据源进行复杂的查询操作,显著提高代码的简洁性、可维护性以及开发效率。
常用的方法
示例代码的参数可以简单理解为集合里的某一项,然后进行遍历
过滤数据
方法名 | 功能描述 | 示例代码 |
---|---|---|
Where | 过滤集合中满足条件的元素 | numbers.Where(n => n > 5); |
OfType<T> | 过滤出指定类型的元素 | objects.OfType<int>(); |
投影数据
方法名 | 功能描述 | 示例代码 |
---|---|---|
Select | 将集合中的元素映射到新的形式 | numbers.Select(n => n * 2); |
SelectMany | 将嵌套集合展开并映射 | students.SelectMany(s => s.Courses); |
排序数据
方法名 | 功能描述 | 示例代码 |
---|---|---|
OrderBy | 按升序排序 | students.OrderBy(s => s.Age); |
OrderByDescending | 按降序排序 | students.OrderByDescending(s => s.Age); |
ThenBy | 在 OrderBy 后按另一条件排序 | students.OrderBy(s => s.Age).ThenBy(s => s.Name); |
ThenByDescending | 在 OrderBy 后按另一条件降序排序 | students.OrderBy(s => s.Age).ThenByDescending(s => s.Name); |
集合操作
方法名 | 功能描述 | 示例代码 |
---|---|---|
Distinct | 去重 | numbers.Distinct(); |
Union | 合并两个集合并去重 | numbers1.Union(numbers2); |
Intersect | 取两个集合的交集 | numbers1.Intersect(numbers2); |
Except | 取两个集合的差集 | numbers1.Except(numbers2); |
聚合操作
方法名 | 功能描述 | 示例代码 |
---|---|---|
Sum | 求和 | numbers.Sum(); |
Average | 求平均值 | numbers.Average(); |
Max | 求最大值 | numbers.Max(); |
Min | 求最小值 | numbers.Min(); |
Count | 统计元素个数 | numbers.Count(); |
分组操作
方法名 | 功能描述 | 示例代码 |
---|---|---|
GroupBy | 按指定键分组 | students.GroupBy(s => s.Grade); |
查找元素
方法名 | 功能描述 | 示例代码 |
---|---|---|
First | 返回第一个满足条件的元素 | numbers.First(n => n > 5); |
FirstOrDefault | 返回第一个满足条件的元素,若无则返回默认值 | numbers.FirstOrDefault(n => n > 5); |
Single | 返回唯一满足条件的元素 | numbers.Single(n => n == 5); |
SingleOrDefault | 返回唯一满足条件的元素,若无则返回默认值 | numbers.SingleOrDefault(n => n == 5); |
Last | 返回最后一个满足条件的元素 | numbers.Last(n => n > 5); |
LastOrDefault | 返回最后一个满足条件的元素,若无则返回默认值 | numbers.LastOrDefault(n => n > 5); |
其他操作
方法名 | 功能描述 | 示例代码 |
---|---|---|
Any | 判断集合中是否有满足条件的元素 | numbers.Any(n => n > 10); |
All | 判断集合中所有元素是否满足条件 | numbers.All(n => n > 0); |
Skip | 跳过指定数量的元素 | numbers.Skip(5); |
Take | 获取指定数量的元素 | numbers.Take(5); |
Concat | 连接两个集合 | numbers1.Concat(numbers2); |
Reverse | 反转集合 | numbers.Reverse(); |
常用的集合类
操作方法
List<T>
List<T>
是动态数组,提供了丰富的操作方法。
方法名 | 功能描述 | 示例代码 |
---|---|---|
Add | 添加一个元素到列表末尾 | list.Add(10); |
AddRange | 添加一个集合到列表末尾 | list.AddRange(new[] { 20, 30 }); |
Insert | 在指定索引处插入一个元素 | list.Insert(1, 40); |
Remove | 移除第一个匹配的元素 | list.Remove(10); |
RemoveAt | 移除指定索引处的元素 | list.RemoveAt(2); |
RemoveRange | 移除指定范围的元素 | list.RemoveRange(0, 2); |
Clear | 清空列表 | list.Clear(); |
Contains | 判断列表是否包含某个元素 | list.Contains(10); |
IndexOf | 查找元素的索引 | list.IndexOf(10); |
Find | 查找第一个匹配的元素 | list.Find(x => x > 5); |
FindAll | 查找所有匹配的元素 | list.FindAll(x => x > 5); |
Sort | 对列表进行排序 | list.Sort(); |
Reverse | 反转列表 | list.Reverse(); |
Count | 获取列表的元素数量 | list.Count; |
ToArray | 将列表转换为数组 | list.ToArray(); |
LinkedList<T>
LinkedList<T>
是双向链表,适合频繁插入和删除操作。
方法名 | 功能描述 | 示例代码 |
---|---|---|
AddFirst | 在链表头部插入一个元素 | linkedList.AddFirst(10); |
AddLast | 在链表尾部插入一个元素 | linkedList.AddLast(20); |
AddBefore | 在指定节点前插入一个元素 | linkedList.AddBefore(linkedList.First, 30); |
AddAfter | 在指定节点后插入一个元素 | linkedList.AddAfter(linkedList.First, 40); |
RemoveFirst | 移除链表头部的元素 | linkedList.RemoveFirst(); |
RemoveLast | 移除链表尾部的元素 | linkedList.RemoveLast(); |
Remove | 移除第一个匹配的元素 | linkedList.Remove(10); |
Clear | 清空链表 | linkedList.Clear(); |
Contains | 判断链表是否包含某个元素 | linkedList.Contains(10); |
Count | 获取链表的元素数量 | linkedList.Count; |
First | 获取链表的第一个节点 | linkedList.First; |
Last | 获取链表的最后一个节点 | linkedList.Last; |
HashSet<T>
HashSet<T>
是无序且唯一的集合,适合需要快速查找、插入和删除的场景。
方法名 | 功能描述 | 示例代码 |
---|---|---|
Add | 添加一个元素,若已存在则返回 false | hashSet.Add(10); |
Remove | 移除指定元素 | hashSet.Remove(10); |
Clear | 清空集合 | hashSet.Clear(); |
Contains | 判断集合是否包含指定元素 | hashSet.Contains(10); |
UnionWith | 并集操作 | hashSet.UnionWith(otherSet); |
IntersectWith | 交集操作 | hashSet.IntersectWith(otherSet); |
ExceptWith | 差集操作 | hashSet.ExceptWith(otherSet); |
SymmetricExceptWith | 对称差集操作(只保留不重叠的元素) | hashSet.SymmetricExceptWith(otherSet); |
Count | 获取集合的元素数量 | hashSet.Count; |
Dictionary<TKey, TValue>
Dictionary<TKey, TValue>
是键值对集合,支持通过键快速查找值。
方法名 | 功能描述 | 示例代码 |
---|---|---|
Add | 添加一个键值对 | dict.Add("key1", "value1"); |
Remove | 移除指定键的键值对 | dict.Remove("key1"); |
Clear | 清空字典 | dict.Clear(); |
ContainsKey | 判断字典是否包含指定键 | dict.ContainsKey("key1"); |
ContainsValue | 判断字典是否包含指定值 | dict.ContainsValue("value1"); |
TryGetValue | 尝试获取指定键的值,返回是否成功 | dict.TryGetValue("key1", out string value); |
Keys | 获取所有键的集合 | dict.Keys; |
Values | 获取所有值的集合 | dict.Values; |
Count | 获取字典的元素数量 | dict.Count; |
方法示例
List<T>
:动态数组
使用场景:元素频繁增删改查,但不要求唯一性。
// 创建并添加元素
List<string> list = new List<string> { "Apple", "Banana" };
list.Add("Cherry"); // 添加到末尾// 删除元素
list.Remove("Banana"); // 删除第一次出现的元素
list.RemoveAt(0); // 删除索引位置元素// 遍历(LINQ格式)
list.ForEach(fruit => Console.WriteLine(fruit));
LinkedList<T>
:双向链表
使用场景:频繁在两端的插入/删除操作。
LinkedList<int> linkedList = new LinkedList<int>();
linkedList.AddLast(10); // 尾部添加
linkedList.AddFirst(20); // 头部添加LinkedListNode<int> node = linkedList.Find(10);
linkedList.AddAfter(node, 15); // 在节点后插入新值linkedList.RemoveFirst(); // 删除头节点
HashSet<T>
:唯一无序集合
使用场景:去重、集合运算(并集/交集)。
HashSet<int> setA = new HashSet<int> { 1, 2, 3 };
HashSet<int> setB = new HashSet<int> { 3, 4, 5 };setA.UnionWith(setB); // 并集:1, 2, 3, 4, 5
setA.IntersectWith(setB); // 交集:3
setA.ExceptWith(setB); // 差集:1, 2bool contains = setA.Contains(3); // 检查是否包含
Dictionary<TKey, TValue>
:键值对集合
使用场景:高效查找(通过键)、存储复杂数据。
Dictionary<string, int> ages = new Dictionary<string, int>
{{ "Alice", 25 },{ "Bob", 30 }
};ages["Charlie"] = 35; // 添加新键值对
ages.Remove("Bob"); // 删除键值对if (ages.ContainsKey("Alice")) // 检查键是否存在
{int age = ages["Alice"]; // 通过键获取值
}
场景代码示例
从列表中筛选并排序
var students = new List<Student>
{new Student { Name = "Alice", Age = 20 },new Student { Name = "Bob", Age = 22 },new Student { Name = "Charlie", Age = 19 }
};var result = students.Where(s => s.Age >= 20) // 筛选年龄 >= 20 的学生.OrderBy(s => s.Age) // 按年龄升序排序.Select(s => s.Name); // 投影名字
统计字符串中每个单词的出现次数
string text = "Hello world! Hello C#!";
var wordCounts = text.Split(' ').GroupBy(word => word).Select(group => new { Word = group.Key, Count = group.Count() });
foreach (var word in wordCounts)
{Console.WriteLine($"{word.Word}: {word.Count}");
}
使用 Dictionary
和 LINQ 实现缓存
Dictionary<int, string> cache = new Dictionary<int, string>();
cache[1] = "Value1";
cache[2] = "Value2";var cachedKeys = cache.Keys.Where(key => key % 2 == 0); // 查找偶数键
总结
集合类和 LINQ 不仅简化了数据的存储和查询,还极大地提升了代码的可读性和开发效率。掌握集合类和 LINQ 能够编写更高效、更易维护的代码。如何高效地管理和处理数据,是每个开发者都需要面对的关键问题。