一直没好好地学习一下LINQ,只会平时常用的一几个。
师傅这几天问到,就顺便整理了一下。
以下是几个平时未用到的。
一、ToLookup
签名:
public static ILookup<TKey, TSource> ToLookup<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector
)
解说:
与GroupBy功能差不多,都会创建类字典集合,区别在于:
GroupBy是延迟加载,所以即使使用GroupBy得到结果集合,若原操作目标集合发生改变,那结果集合的元素也会发生相应的改变。
创建一个ILookup集合,此集合不像Dictionary,其元素是不可改变的。
非延迟执行。
示例:
public sealed class Product
{
public int Id { get; set; }
public string Category { get; set; }
public double Value { get; set; }
public override string ToString()
{
return string.Format("[{0}: {1} - {2}]", Id, Category, Value);
}
}
public static void Test()
{
var products = new List<Product>
{
new Product {Id = 1, Category = "Electronics", Value = 15.0},
new Product {Id = 2, Category = "Groceries", Value = 40.0},
new Product {Id = 3, Category = "Garden", Value = 210.3},
new Product {Id = 4, Category = "Pets", Value = 2.1},
new Product {Id = 5, Category = "Electronics", Value = 19.95},
new Product {Id = 6, Category = "Pets", Value = 21.25},
new Product {Id = 7, Category = "Pets", Value = 5.50},
new Product {Id = 8, Category = "Garden", Value = 13.0},
new Product {Id = 9, Category = "Automotive", Value = 10.0},
new Product {Id = 10, Category = "Electronics", Value = 250.0},
};
//若使用GroupBy,则所有Garden产品最后不会被打印出来
//若使用ToLookup,则所有Garden产品最后还是会被打印出来
var groups = products.ToLookup(pr => pr.Category);
//删除所有属于Garden的产品
products.RemoveAll(pr => pr.Category == "Garden");
//打印结果
foreach (var group in groups)
{
Console.WriteLine(group.Key);
foreach (var item in group)
{
Console.WriteLine("\t" + item);
}
}
}
二、Zip
签名:
public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult>(
this IEnumerable<TFirst> first,
IEnumerable<TSecond> second,
Func<TFirst, TSecond, TResult> resultSelector
)
解说:
合并两个序列。
结果序列的元素个数为两个序列中的元素个数较少的。
延迟执行。
示例:
int[] numbers = { 1, 2, 3, 4 };
string[] words = { "one", "two", "three" };
var numbersAndWords = numbers.Zip(words, (first, second) => first + " " + second);
foreach (var item in numbersAndWords)
Console.WriteLine(item);
// This code produces the following output:
// 1 one
// 2 two
// 3 three
三、Repeat
签名:
public static IEnumerable<TResult> Repeat<TResult>(
TResult element,
int count
)
解说:
生成包含一个重复值的序列
注意非扩展方法。
延迟执行。
示例:
IEnumerable<string> strings = Enumerable.Repeat("I like programming.", 15);
foreach (String str in strings)
{
Console.WriteLine(str);
}
/*
This code produces the following output:
I like programming.
I like programming.
I like programming.
I like programming.
I like programming.
I like programming.
I like programming.
I like programming.
I like programming.
I like programming.
I like programming.
I like programming.
I like programming.
I like programming.
I like programming.
*/
四、Range
签名:
public static IEnumerable<int> Range(
int start,
int count
)
解说:
生成指定范围内的整数的序列。
延迟执行。
示例:
IEnumerable<int> squares = Enumerable.Range(1, 5);
foreach (var num in squares)
{
Console.WriteLine(num);
}
/*
This code produces the following output:
1
2
3
4
5
*/
五、OfType
签名:
public static IEnumerable<TResult> OfType<TResult>(
this IEnumerable source
)
解说:
根据指定类型筛选 IEnumerable 的元素。
延迟执行。
示例:
System.Collections.ArrayList fruits = new System.Collections.ArrayList(4);
fruits.Add("Mango");
fruits.Add("Orange");
fruits.Add("Apple");
fruits.Add(3.0);
fruits.Add(4.0);
fruits.Add(5);
fruits.Add("6.0");
// Apply OfType() to the ArrayList.
IEnumerable<double > query1 = fruits.OfType<double>();
Console.WriteLine("Elements of type 'double' are:");
foreach (var element in query1)
{
Console.WriteLine(element);
}
// This code produces the following output:
//
// Elements of type 'double' are:
// 3
// 4
六:Join
签名:
public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>(
this IEnumerable<TOuter> outer,
IEnumerable<TInner> inner,
Func<TOuter, TKey> outerKeySelector,
Func<TInner, TKey> innerKeySelector,
Func<TOuter, TInner, TResult> resultSelector
)
解说:
延迟执行。
用法与SQL中的JOIN用法相似,参考以下的SQL:
USE pubs
SELECT a.au_fname, a.au_lname, p.pub_name
FROM authors a LEFT OUTER JOIN publishers p
ON a.city = p.city
示例:
class Person
{
public string Name { get; set; }
}
class Pet
{
public string Name { get; set; }
public Person Owner { get; set; }
}
public static void JoinEx1()
{
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 };
// Create a list of Person-Pet pairs where
// each element is an anonymous type that contains a
// Pet's name and the name of the Person that owns the Pet.
var query =
people.Join(pets,
person => person,
pet => pet.Owner,
(person, pet) =>
new { OwnerName = person.Name, Pet = pet.Name });
foreach (var obj in query)
{
Console.WriteLine(
"{0} - {1}",
obj.OwnerName,
obj.Pet);
}
}
/*
This code produces the following output:
Hedlund, Magnus - Daisy
Adams, Terry - Barley
Adams, Terry - Boots
Weiss, Charlotte - Whiskers
*/