LINQ学习总结
-
- 获取数据源
- 创建查询
- 方法语法
- 标准查询运算符
-
-
- Cast
- GroupBy
- GroupJoin
- Join
- OrderBy
- OrderByDescending
- ThenBy
- ThenByDescending
- Select
- SelectMany
- Where
- Aggregate
- All 是否都满足条件
- Any 是否包含
- Average 平均值
- Concat 组合
- Except 差集
- Intersect 交集
- Union 并集
- Contains 是否包含
- Count 数量
- Distinct 去重
- ElementAt
- ElementAtOrDefault
- Empty 指定类型空值
- First 第一个
- FirstOrDefault
- Last 最后一个
- LastOrDefault
- Max
- Min
- OfType 指定类型筛选元素
- Range
- Repeat
- SequanceEqual 比较元素
- Single 单个特定元素
- SingleOrDefault
- Sum
- Reverse 反转
- Skip
- SkipWhile
- Take
- TakeWhile
- ToArray
- ToList
- ToDictionary
- ToLookup
-
- 执行方式
获取数据源
语句:from 范围变量 in 数据源
可查询类型(支持IEnumberable或派生接口,如泛型IQueryable 的类型)无需修改或处理就可作为LINQ数据源。
如果源数据不是可查询类型,则LINQ提供程序必须以此方式表示源数据,如下操作。
//LINQ to XML 将 XML 文档加载到可查询的 XElement 类型中
XElement contacts = XElement.Load(@"c:\myContactList.xml");
//LINQ to SQL
Northwnd db = new Northwnd(@"c:\northwnd.mdf");
IQueryable<Customer> custQuery =
from cust in db.Customers
where cust.City == "London"
select cust;
可以通过使用let子句引入其他范围变量
在一般情况下,编译器可以直接推断范围变量的类型,而若数据源是非泛型IEnumerable集合,必须显式声明范围变量的类型,如下操作。
//arrayList为非泛型的ArrayList集合
var query=from Student s in arrayList;
创建查询
from子句
from子句
```csharp
var lowNums = from num in numbers
where num < 5
select num;
```
复合from子句
```csharp
var scoreQuery = from student in students
from score in student.Scores
where score > 90
select new { Last = student.LastName, score };
```
筛选(where子句)
使用where子句,仅返回表达式为true的元素。可以使用“&&”和“||”应用更多的筛选器表达式。
csharp var queryLondonCustomers = from cust in customers where cust.City == "London" && cust.Name == "Devon" select cust;
orderby子句
对返回的数据排序,ascending为顺序,descending为逆序,默认为顺序
```csharp
class OrderbySample1
{
static void Main()
{
// Create a delicious data source.
string[] fruits = { "cherry", "apple", "blueberry" };
// 顺序排序.
IEnumerable<string> sortAscendingQuery =
from fruit in fruits
orderby fruit //"ascending" is default
select fruit;
}
}
/* Output:
Ascending:
apple
blueberry
cherry
```
///Dictionary例子
public static void Main(string[] args)
{
Dictionary<int, string> dictionary = new Dictionary<int, string> {
{1, "cherry"},{3,"apple"},{2,"blueberry"}};
IOrderedEnumerable<KeyValuePair<int, string>> sortAscendingQuery =
from fruit in dictionary
orderby fruit.Key//"ascending" is default
select fruit;
// Solution solution = new Solution();
// int x = solution.MakeStringSorted("cdbea");
foreach (var valuePair in sortAscendingQuery)
{
Console.WriteLine(valuePair.Value);
}
}
/* Output:
cherry
blueberry
apple
group by子句
语句:group item by key
根据指定的键分组
```csharp
var queryCustomersByCity =
from cust in customers
group cust by cust.City;
foreach (var customerGroup in queryCustomersByCity)
{
Console.WriteLine(customerGroup.Key);
foreach (Customer customer in customerGroup)
{
Console.WriteLine(" {0}", customer.Name);
}
}
///Dictionary例子
public static void Main(string[] args)
{
Dictionary<int, string> dictionary = new Dictionary<int, string> {
{1, "aa"},{3,"bb"},{2,"aa"}};
var queryCustomersByCity =
from cust in dictionary
group cust by cust.Value;
foreach (var customerGroup in queryCustomersByCity)
{
Console.WriteLine(customerGroup.Key);
foreach (var item in customerGroup)
{
Console.WriteLine(" {0}", item.Key);
}
}
Console.WriteLine("Press any key to exit");
Console.ReadKey();
}
Output:
aa
1
2
bb
3
如上操作的结果为列表形式,列表元素带有Key,所有元素根据key来分组。
语句:group item by key into group
使用into可以得到范围变量,能直接引用某个组操作
```csharp
// custQuery is an IEnumerable<IGrouping<string, Customer>>
var custQuery =
from cust in customers
group cust by cust.City into custGroup
where custGroup.Count() > 2
orderby custGroup.Key
select custGroup;
```
///Dictionary例子
public static void Main(string[] args)
{
Dictionary<int, string> dictionary = new Dictionary<int, string> {
{3,"bb"},{2,"aa"},{1, "aa"}};
var queryCustomersByCity =
from cust in dictionary
group cust by cust.Value into custGroup
orderby custGroup.Key
select custGroup;
foreach (var customerGroup in queryCustomersByCity)
{
Console.WriteLine(customerGroup.Key);
foreach (var item in customerGroup)
{
Console.WriteLine(" {0}", item.Key);
}
}
Console.WriteLine("Press any key to exit");
Console.ReadKey();
}
Output:
aa
2
1
bb
3
join子句
语句:join item in itemResource on item.property equals preItem.property
在 LINQ 中,join 子句始终作用于对象集合,而非直接作用于数据库表。
```csharp
//查找所有位置相同的客户和分销商
var innerJoinQuery =
from cust in customers
join dist in distributors on cust.City equals dist.City
select new { CustomerName = cust.Name, DistributorName = dist.Name };
///Dictionary例子
public static void Main(string[] args)
{
Dictionary<int, Customer> customers = new Dictionary<int, Customer>
{
{1, new Customer() {city = "hangzhou", name = "wry"}},
{2, new Customer() {city = "ningbo", name = "wry2"}}
};
Dictionary<int,Distributor> distributors = new Dictionary<int, Distributor>
{
{1, new Distributor() {city = "hangzhou", name = "wry3"}},
{2, new Distributor() {city = "ningbo", name = "wry4"}}
};
var queryCustomersByCity =
from cust in customers
join distributor in distributors on cust.Value.city equals distributor.Value.city
select new {CustName = cust.Value.name, DistName = distributor.Value.name};
foreach (var item in queryCustomersByCity)
{
Console.WriteLine("{0} {1}",item.CustName,item.DistName);
}
Console.WriteLine("Press any key to exit");
Console.ReadKey();
}
Output:
wry wry3
wry2 wry4
Press any key to exit
```
select子句
查询表达式必须以 select 子句或 group 子句结尾。 在最简单的情况下,select 子句仅指定范围变量, 这时返回的序列包含与数据源类型相同的元素。此外,select 子句还提供了强大的机制,用于将源数据转换(或投影)为新类型。
```csharp
var query = from cust in Customer
select new {Name = cust.Name, City = cust.City};
///Dictionary例子
public static void Main(string[] args)
{
Dictionary<int, Customer> customers = new Dictionary<int, Customer>
{
{1, new Customer() {city = "hangzhou", name = "wry"}},
{2, new Customer() {city = "ningbo", name = "wry2"}}
};
Dictionary<int,Distributor> distributors = new Dictionary<int, Distributor>
{
{1, new Distributor() {city = "hangzhou", name = "wry3"}},
{2, new Distributor() {city = "ningbo", name = "wry4"}}
};
var queryCustomersByCity =
from cust in customers
join distributor in distributors on cust.Value.city equals distributor.Value.city
select new {CustName = cust.Value.name, DistName = distributor.Value.name};
foreach (var item in queryCustomersByCity)
{
Console.WriteLine("{0} {1}",item.CustName,item.DistName);
}
Console.WriteLine("Press any key to exit");
Console.ReadKey();
}
Output:
wry wry3
wry2 wry4
Press any key to exit
```
方法语法
上述的方法皆属于查询语法。查询语法和方法语法在语义上是相同的,但是查询语法更简单且更易于阅读。 某些查询必须表示为方法调用(比如.Count()的查询)。
```csharp
//查询语法:
IEnumerable<int> numQuery1 =
from num in numbers
where num % 2 == 0
orderby num
select num;
//方法语法:
IEnumerable<int> numQuery2 = numbers.Where(num => num % 2 == 0).OrderBy(n => n);
///Dictionary例子
//查询语法:
Dictionary<int, int> dictionary = new Dictionary<int, int>();
dictionary.Add(1,7);
dictionary.Add(2,2);
dictionary.Add(3,8);
dictionary.Add(4,3);
dictionary.Add(5,4);
IOrderedEnumerable<KeyValuePair<int, int>> numQuery1 =
from num in dictionary
where num.Value % 2 == 0
orderby num.Value
select num;
foreach (var item in numQuery1)
{
Console.WriteLine("{0}",item.Key);
}
Console.WriteLine("Press any key to exit");
Console.ReadKey();
Output:
2
5
3
//方法语法
Dictionary<int, int> dictionary = new Dictionary<int, int>();
dictionary.Add(1,7);
dictionary.Add(2,2);
dictionary.Add(3,8);
dictionary.Add(4,3);
dictionary.Add(5,4);
IOrderedEnumerable<KeyValuePair<int, int>> numQuery2 = dictionary.Where(num => num.Value % 2 == 0)
.OrderBy(num => num.Value);
foreach (var item in numQuery2)
{
Console.WriteLine("{0}",item.Key);
}
Console.WriteLine("Press any key to exit");
Console.ReadKey();
Output:
2
5
3
标准查询运算符
Cast
执行方式:流式处理
将 IEnumerable 的元素强制转换为指定的类型。
```csharp
IEnumerable<string> query =
fruits.Cast<string>().OrderBy(fruit => fruit).Select(fruit => fruit);
///Dictionary例子
Dictionary<int, string> dictionary = new Dictionary<int, string>();
dictionary.Add(1,"aa");
dictionary.Add(2,"cc");
dictionary.Add(3,"bb");
dictionary.Add(4,"ff");
dictionary.Add(5,"ee");
var numQuery2 = dictionary.Cast<KeyValuePair<int,string>>().OrderBy(num => num.Value);
foreach (var item in numQuery2)
{
Console.WriteLine(item.Key);
}
Console.WriteLine("Press any key to exit");
Console.ReadKey();
Output:
1
3
2
5
4
Press any key to exit
```
GroupBy
执行方式:非流式处理
根据指定的键选择器函数对序列中的元素进行分组,并且从每个组及其键中创建结果值。 通过使用指定的函数对每个组的元素进行投影。
```csharp
public static void GroupByEx4()
{
// Create a list of pets.
List petsList =
new List{ new Pet { Name=“Barley”, Age=8.3 },
new Pet { Name=“Boots”, Age=4.9 },
new Pet { Name=“Whiskers”, Age=1.5 },
new Pet { Name=“Daisy”, Age=4.3 } };
var query = petsList.GroupBy(
pet => Math.Floor(pet.Age), //key
pet => pet.Age, //element
(baseAge, ages) => new
{
Key = baseAge,
Count = ages.Count(),
Min = ages.Min(),
Max = ages.Max()
}); //结果集(key,IEnumerable groupList)
// Iterate over each anonymous type.
foreach (var result in query)
{
Console.WriteLine("\nAge group: " + result.Key);
Console.WriteLine("Number of pets in this age group: " + result.Count);
Console.WriteLine("Minimum age: " + result.Min);
Console.WriteLine("Maximum age: " + result.Max);
}
/* This code produces the following output:
Age group: 8
Number of pets in this age group: 1
Minimum age: 8.3
Maximum age: 8.3
Age group: 4
Number of pets in this age group: 2
Minimum age: 4.3
Maximum age: 4.9
Age group: 1
Number of pets in this age group: 1
Minimum age: 1.5
Maximum age: 1.5
*/
///Dictionary例子
Dictionary<int, string> dictionary = new Dictionary<int, string>();
dictionary.Add(1,"aa");
dictionary.Add(2,"cc");
dictionary.Add(3,"aa");
dictionary.Add(4,"cc");
dictionary.Add(5,"ee");
var numQuery2 = dictionary.GroupBy(item => item.Value);
foreach (var group in numQuery2)
{
Console.WriteLine(group.Key);
foreach (var item in group)
{
Console.WriteLine(" {0}",item.Key);
}
}
Console.WriteLine("Press any key to exit");
Console.ReadKey();
Output:
aa
1
3
cc
2
4
ee
5
Press any key to exit
```
GroupJoin
执行方式:流式处理和非流式处理
基于键值等同性对两个序列的元素进行关联,并对结果进行分组。 使用指定的 IEqualityComparer 对键进行比较。
```csharp
Person magnus = new Person { Name = "Hedlund, Magnus" };
Person terry = new Person { Name = "Adams, Terry" };
Person charlotte = new Person { Name = "Weiss, Charlotte" };
Pet barley = new Pet { Name = "Barley", Owner = terry };
Pet boots = new Pet { Name = "Boots", Owner = terry };
Pet whiskers = new Pet { Name = "Whiskers", Owner = charlotte };
Pet daisy = new Pet { Name = "Daisy", Owner = magnus };
List<Person> people = new List<Person> { magnus, terry, charlotte };
List<Pet> pets = new List<Pet> { barley, boots, whiskers, daisy };
var query = //返回IEnumerable<result>
people.GroupJoin(pets, //要联接的序列
person => person, //第一个序列中提取联接键,按键分组
pet => pet.Owner, //第二个序列中提取联接键
(person, petCollection) => //创建结果元素
new
{
OwnerName = person.Name,
Pets = petCollection.Select(pet => pet.Name)
});
foreach (var obj in query)
{
// Output the owner's name.
Console.WriteLine("{0}:", obj.OwnerName);
// Output each of the owner's pet's names.
foreach (string pet in obj.Pets)
{
Console.WriteLine(" {0}", pet);
}
}
/*
This code produces the following output:
Hedlund, Magnus:
Daisy
Adams, Terry:
Barley
Boots
Weiss, Charlotte:
Whiskers
*/
///Dictionary例子
Dictionary<int, Customer> customers = new Dictionary<int, Customer>
{
{1, new Customer() {city = "hangzhou", name = "wry"}},
{2, new Customer() {city = "ningbo", name = "wry2"}}
};
Dictionary<int,Distributor> distributors = new Dictionary<int, Distributor>
{
{1, new Distributor() {city = "hangzhou", name = "wry3"}},
{2, new Distributor() {city = "ningbo", name = "wry4"}}
};
var query = customers.GroupJoin(distributors,
custCity => custCity.Value.city,
distCity => distCity.Value.city,
(custName, collection) =>
new
{
custN = custName.Value.name,
distN = collection.Select(dist => dist.Value.name)
}
);
foreach (var group in query)
{
Console.WriteLine(group.custN);
foreach (var item in group.distN)
{
Console.WriteLine(" {0}",item);
}
}
Console.WriteLine("Press any key to exit");
Console.ReadKey();
Output:
wry
wry3
wry2
wry4
Press any key to exit
```
Join
执行方式:流式处理与非流式处理
基于匹配键对两个序列的元素进行关联。
```csharp
var query =
people.Join(pets, //要联接的序列
person => person, //第一个序列中提取联接键
pet => pet.Owner, //第二个序列中提取联接键
(person, pet) => //创建结果元素
new { OwnerName = person.Name, Pet = pet.Name });
///Dictionary例子
Dictionary<int, Customer> customers = new Dictionary<int, Customer>
{
{1, new Customer() {city = "hangzhou", name = "wry"}},
{2, new Customer() {city = "ningbo", name = "wry2"}}
};
Dictionary<int,Distributor> distributors = new Dictionary<int, Distributor>
{
{1, new Distributor() {city = "hangzhou", name = "wry3"}},
{2, new Distributor() {city = "ningbo", name = "wry4"}}
};
var query = customers.Join(distributors,
custCity => custCity.Value.city,
distCity => distCity.Value.city,
(custName, distName) =>
new
{
custN = custName.Value.name,
distN = distName.Value.name
}
);
foreach (var group in query)
{
Console.WriteLine("{0} {1}",group.custN,group.distN);
}
Console.WriteLine("Press any key to exit");
Console.ReadKey();
Output:
wry wry3
wry2 wry4
Press any key to exit
```
OrderBy
执行方式:非流式处理
根据键按升序对序列的元素进行排序。
```csharp
IEnumerable<Pet> query = pets.OrderBy(pet => pet.Age);
///Dictionary例子
Dictionary<int, string> dictionary = new Dictionary<int, string>();
dictionary.Add(1,"aa");
dictionary.Add(2,"cc");
dictionary.Add(3,"bb");
dictionary.Add(4,"ff");
dictionary.Add(5,"ee");
var numQuery2 = dictionary.Cast<KeyValuePair<int,string>>().OrderBy(num => num.Value);
foreach (var item in numQuery2)
{
Console.WriteLine(item.Key);
}
Console.WriteLine("Press any key to exit");
Console.ReadKey();
Output:
1
3
2
5
4
Press any key to exit
```
OrderByDescending
执行方式:非流式处理
根据键按降序对序列的元素进行排序。
```csharp
IEnumerable<Pet> query = pets.OrderByDescending(pet => pet.Age);
///Dictionary例子
Dictionary<int, string> dictionary = new Dictionary<int, string>();
dictionary.Add(1,"aa");
dictionary.Add(2,"cc");
dictionary.Add(3,"bb");
dictionary.Add(4,"ff");
dictionary.Add(5,"ee");
var numQuery2 = dictionary.Cast<KeyValuePair<int,string>>().OrderByDescending(num => num.Value);
foreach (var item in numQuery2)
{
Console.WriteLine(item.Key);
}
Console.WriteLine("Press any key to exit");
Console.ReadKey();
Output:
4
5
2
3
1
Press any key to exit
```
ThenBy
执行方式:非流式处理
根据某个键按升序对序列中的元素执行后续排序。
```csharp
IEnumerable<string> query =
fruits.OrderBy(fruit => fruit.Length).ThenBy(fruit => fruit);
///Dictionary例子
Dictionary<int, string> dictionary = new Dictionary<int, string>();
dictionary.Add(2,"aa");
dictionary.Add(4,"aa");
dictionary.Add(1,"aa");
dictionary.Add(3,"bb");
dictionary.Add(5,"bb");
var numQuery2 = dictionary.Cast<KeyValuePair<int,string>>().OrderBy(num => num.V