查询运算符是组成Linq模式的方法。这些方法中的大多数都作用于序列;其中序列指其类型实现IEnumberable
接口或IQueryable
接口的对象。标准查询运算符提供包括筛选、投影、集合、排序等查询功能。
查询运算符包含两组,一组作用于类型IEnumberable
的对象,另一组作用于类型IQueryable
的对象。
筛选是指将结果集限制为仅包含满足指定条件的元素的操作。它也称为选定内容。筛选数据方法包含OfType和Where。
string[] list=["A","AB","BC","CD","DE","EF"];
IEnumerable query = from chars in list where chars.Contains("B") select chars;
foreach(string ch in query){
Console.WriteLine(str);
}
运行结果:
AB
BC
投影是指将对象转换为一种新形式的操作,该形式通常只包含那些将随后使用的属性。通过使用投影,可以构造从每个对象生成的新类型。可以投影属性,并对属性执行数学函数。
string[] list={"A","AB","BC","CD","DE","EF"};
IEnumerable query = from chars in list select chars.ToLower();
foreach(string ch in query){
Console.WriteLine(str)
}
运行结果
a
ab
bc
cd
de
ef
使用多个from子句来投影字符串列表中每个字符串的每个字符转变为大写。
string[] list = { "A|B|C|D","E|F|G|H"};
IEnumerable query = from chars in list
from ch in chars.Split('|')
select ch;
foreach (string ch in query)
{
Console.WriteLine(ch)
}
运行结果
A
B
C
D
E
F
G
H
Zip投影运算符有多个重载,所有Zip方法都处理两个或更多可能是异构类型的序列。前两个重载返回元组,具有来自给定序列的响应位置类型。
int[] index = { 1, 2, 3 };
string[] chars = { "A", "B", "C" };
IEnumerable zip = chars.Zip(index, (n, w) => n + "=" + w);
foreach (var z in zip)
{
Console.WriteLine(z);
}
运行结果
A=1
B=2
C=3
zip操作生成的序列的长度永远不会长于最短序列。index和letters集合的长度不同,生成的序列将省略index集合中的最后一个元素,因为它没有任何要压缩的内容。
Select
与SelectMany
的工作都是依据源生成一个或多个结构值。Select
为每个源值生成一个结构值。因此,总体结构是一个与源集合具有相同元素数目的集合。 与之相反,SelectMany
生成单个总体结果,其中包含来自每个源值的串联子集合。 作为参数传递到 SelectMany
的转换函数必须为每个源值返回一个可枚举值序列。 然后,SelectMany
串联这些可枚举序列,以创建一个大的序列。
LINQ 中的集运算是指根据相同或不同集合(或集)中是否存在等效元素来生成结果集的查询运算。
删除集合中的重复元素
int[] index = { 1, 2, 3 ,4};
string[] chars = { "A", "B", "C" , "B", "C" ,"D"};
IEnumerable zip = from ch in chars.Distinct() select ch;
foreach (var z in zip)
{
Console.WriteLine(z);
}
运行结果
A
B
C
D
在新.NET Framework中可以使用DistinctBy
替代Distinct
,DistinctBy
采用keySelector。keySelector
用作源类型的比较鉴别器。
Except返回的序列只包含位于第一个输入序列但不位于第二个输入序列的元素。
string[] listA = { "A", "B", "AC", "BC", "CD" };
string[] chars = { "A", "B", "C" , "B", "C" ,"D"};
IEnumerable listC = from ch in chars.Except(listA) select ch;
foreach (var z in listC)
{
Debug.WriteLine(z);
}
运行结果
C
D
ExceptBy
方法是 Except
的替代方法,它采用可能是异构类型的两个序列和一个 keySelector
。 keySelector
与第二个集合的类型相同,用作源类型的比较鉴别器。
返回序列包含两个输入序列共有的元素。
string[] listA = { "A", "B", "AC", "BC", "CD" };
string[] chars = { "A", "B", "C" , "B", "C" ,"D"};
IEnumerable listC = from ch in chars.Intersect(listA) select ch;
foreach (var z in listC)
{
Debug.WriteLine(z);
}
运行结果
A
B
IntersectBy
方法是Intersect
的替代方法,它采用可能是异构类型的两个序列和一个keySelector
。keySelector
用作第二个集合类型的比较鉴别器。
两个字符串序列执行的联合操作。返回的序列包含两个输入序列的唯一元素。
string[] listA = { "A", "B", "AC", "BC", "CD" };
string[] chars = { "A", "B", "C" , "B", "C" ,"D"};
IEnumerable listC = from ch in chars.Union(listA) select ch;
foreach (var z in listC)
{
Debug.WriteLine(z);
}
运行结果
A
B
C
D
AC
BC
CD
排序操作基于一个或多个属性对序列的元素进行排序。 第一个排序条件对元素执行主要排序。 通过指定第二个排序条件,您可以对每个主要排序组内的元素进行排序。
结果集按升序对值排序。
string[] listA = { "A", "B", "AC", "BC", "CD" };
string[] chars = { "A", "B", "C" , "B", "C" ,"D"};
IEnumerable listC = from ch in chars.Union(listA) orderby ch select ch;
foreach (var z in listC)
{
Debug.WriteLine(z);
}
运行结果
A
AC
B
BC
C
CD
D
按降序对值排序。C#查询表达式语法orderby… descending
string[] listA = { "A", "B", "AC", "BC", "CD" };
string[] chars = { "A", "B", "C" , "B", "C" ,"D"};
IEnumerable listC = from ch in chars.Union(listA)
orderby ch descending
select ch;
foreach (var z in listC)
{
Debug.WriteLine(z);
}
运行结果
D
CD
C
BC
B
AC
A
按升序执行次要排序。orderby...
,...
string[] listA = { "A", "B", "AC", "BC", "CD" };
string[] chars = { "A", "B", "C" , "B", "C" ,"D"};
IEnumerable listC = from ch in chars.Union(listA) orderby ch,ch.Length select ch;
foreach (var z in listC)
{
Debug.WriteLine(z);
}
运行结果
A
AC
B
BC
C
CD
D
按降序执行次要顺序。C#查询表达式语法orderby…,… descending。
string[] listA = { "AB", "DC", "ED", "FH", "Z" };
IEnumerable listC = from ch in listA
orderby ch descending,ch.Length descending
select ch;
foreach (var z in listC)
{
Debug.WriteLine(z);
}
运行结果
Z
FH
ED
DC
AB
反转集合中元素的顺序
string[] listA = { "AB", "DC", "ED", "FH", "Z" };
IEnumerable listC = listA.Reverse();
foreach (var z in listC)
{
Debug.WriteLine(z);
}
运行结果
Z
FH
ED
DC
AB
限定符运算返回一个Boolean值,该值指示序列中是否有一些元素满足条件或是否所有元素都满足条件。
全部确定是否序列中的所有元素都满足条件
class Marketing
{
public string Name{get;set;}
public string[] Items{get;set;}
}
public static void Main(string[] args)
{
List markets=
{
new Market { Name = "Emily's", Items = {"kiwi", "cheery", "banana"} },
new Market { Name = "Kim's", Items = {"melon", "mango", "olive"} },
new Market { Name = "Adam's", Items = {"kiwi", "apple", "orange"} },
}
var names = from marker in markets
where marker.Items.All(item=>item.Length == 5)
select Name;
foreach(string name in namse)
{
Debug.WriteLine(name);
}
}
使用Any检查所有字符串是否以“o”开头。
class Market
{
public string Name{get;set;}
public string[] Items{get;set;}
}
public static void Main(string[] args)
{
List markets=
{
new Market { Name = "Emily's", Items = {"kiwi", "cheery", "banana"}},
new Market { Name = "Kim's", Items = {"melon", "mango", "olive"} },
new Market { Name = "Adam's", Items = {"kiwi", "apple", "orange"} },
}
IEnumerable names = from market in markets
where market.Items.Any(item=>item.StartsWith("o"))
select market.Name;
foreach(string name in names)
{
Debug.WriteLine(name);
}
}
Contains检查所有数组是否具有特定元素。
class Market
{
public string Name{get;set;}
public string[] Items{get;set;}
}
public static void Main(string[] args)
{
List markets=
{
new Market { Name = "Emily's", Items = {"kiwi", "cheery", "banana"}},
new Market { Name = "Kim's", Items = {"melon", "mango", "olive"} },
new Market { Name = "Adam's", Items = {"kiwi", "apple", "orange"} },
}
IEnumerable names = from market in markets
where market.Items.Contains("kiwi")
select market.Name;
foreach(string name in names)
{
Debug.WriteLine(name);
}
}
Linq中的数据分区是指将输入序列划分为两个部分的操作,无需重新排列元素,然后返回其中一个部分。
Skip跳过序列中指定位置之前的元素。
string[] items ={"A", "B","C","D","E","F","G","H","I"};
var item= items.Skip(5);
foreach (var it in item)
{
Console.WriteLine(it);
}
运行结果
F
G
H
I
Skip指定跳过的数目,SkipWhile指定的跳过条件,而不是元素数。
string[] texts = new string[] { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
IEnumerable skippedTexts = texts.SkipWhile(value => value.EndsWith("n"));
foreach (var it in skippedTexts)
{
Console.WriteLine(it);
}
运行结果
Tue
Wed
Thu
Fri
Sat
获取序列中指定位置之前的元素
string[] texts = new string[] { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
// 删除尾字母为n的
IEnumerable skippedTexts = texts.Take(3);
foreach (var it in skippedTexts)
{
Console.WriteLine(it);
}
运行结果
Sun
Mon
Tue
TakeWhile
操作符用于从输入序列中返回指定数量且满足一定条件的元素。
当TakeWhile
操作符被调用时,会将source序列中的每一个元素顺序传递给委托predicate,只有哪些使用得predicate
返回值为true的元素才会被添加到结果序列中,要特别注意是,当TakeWhile
操作符在查找过程中,遇到第一个返回false的元素就会立即停止执行,跳出,无论后面还有没有符合条件的元素,即使后面有符合条件的元素也不会获取。对于第二个扩展方法,委托里面含有一个int类型的参数。
string[] lists = ["a", "e", "i", "o", "u"];
var takeList = lists.TakeWhile(x => x != "i");
foreach (var al in takeList)
{
Console.WriteLine(al);
}
运行结果
a
e
chunk 该方法将序列的元素拆分为指定大小的区块
string[] lists = {"公孙胜","鲁智深","林冲","吴用","李逵","宋江","武松" };
var nameList = lists.Chunk(3);
foreach (var names in nameList)
{
foreach (var name in names)
{
Trace.WriteLine(name);
}
Trace.WriteLine("****************");
}
运行结果
公孙胜
鲁智深
林冲
****************
吴用
李逵
宋江
****************
武松
****************