重视Linq技术_7

Projecting - Select

//1、Select-Subqueries and Object Hierarchies
string sampleDirectory = Environment.GetFolderPath  (Environment.SpecialFolder.MyDocuments);
DirectoryInfo[] dirs = new DirectoryInfo (sampleDirectory).GetDirectories();
var query =
    from d in dirs 
    where (d.Attributes & FileAttributes.System) == 0
    select new
    {
        DirectoryName = d.FullName,
        Created = d.CreationTime,
        Files = from f in d.GetFiles()
            where (f.Attributes & FileAttributes.Hidden) == 0
            select new { FileName = f.Name, f.Length, }
    };
query.Dump();

//2、Simple SelectMany

var fullNames = new[] { "Anne Williams", "John Fred Smith", "Sue Green" }.AsQueryable();
IEnumerable<string[]> query1 = fullNames.Select     (name => name.Split());
IEnumerable<string>   query2 = fullNames.SelectMany (name => name.Split());
query1.Dump ("A simple Select gives us a hierarchical result set");
query2.Dump ("SelectMany gives us a flat result set");
IEnumerable<string> query3 =
    from fullName in fullNames
    from name in fullName.Split()     // Translates to SelectMany
    select name;
query3.Dump ("Same SelectMany query, but in comprehension syntax");
image
3、Outer Iteration Variables
var fullNames = new[] { "Anne Williams", "John Fred Smith", "Sue Green" }.AsQueryable();
IEnumerable<string> query =
from fullName in fullNames                       // fullName = outer variable
from name in fullName.Split()                    // name = iteration variable
select name + " came from " + fullName;
query.Dump ("Both variables are in scope");
image
//4、The Solution
string[] fullNames = { "Anne Williams", "John Fred Smith", "Sue Green" };

IEnumerable<string> query1 =
    from fullName in fullNames
    from x in fullName.Split().Select (name => new { name, fullName } )
    orderby x.fullName, x.name
    select x.name + " came from " + x.fullName;
query1.Dump ("The intermediate solution");

IEnumerable<string> query2 = fullNames
    .SelectMany (fName => fName.Split().Select (name => new { name, fName } ))
    .OrderBy (x => x.fName)
    .ThenBy  (x => x.name)
    .Select  (x => x.name + " came from " + x.fName);
query2.Dump ("Final translation to lambda syntax");
image

//5、NOTE - Another way to call SelectMany
string[] fullNames = { "Anne Williams", "John Fred Smith", "Sue Green" };
var query1 =
    fullNames
    .SelectMany (fName => fName.Split().Select (name => new { name, fName } ));
// We can re-write this as follows, and get the same result:
var query2 =
    fullNames
    .SelectMany (fName => fName.Split(), (fName, name) => new { name, fName } );
query1.Dump ("Using SelectMany+Select");
query2.Dump ("Using SelectMany with a collection selector + result selector");
image
//6、Cross Product Join - Filtered

var players = new[] { "Tom", "Jay", "Mary" }.AsQueryable();
IEnumerable<string> query =
    from name1 in players
    from name2 in players
    where name1.CompareTo (name2) < 0
    orderby name1, name2
    select name1 + " vs " + name2;
query.Dump();

//7、LINQ to SQL - Outer Joins with SelectMany
(
    from c in Customers
    from p in c.Purchases
    where p.Price > 1000
    select new { c.Name, p.Description, p.Price }
)
.Dump ("An inner join");
(
    from c in Customers
    from p in c.Purchases.DefaultIfEmpty()
    select new { c.Name, p.Description, Price = (decimal?) p.Price }
)
.Dump ("An outer join (without the predicate)");

Customer[] localCustomerCollection = Customers.ToArray();
var query =
from c in localCustomerCollection
from p in c.Purchases.DefaultIfEmpty() 

select new
{
Descript = p == null ? null : p.Description,
Price = p == null ? (decimal?) null : p.Price
};
query.Dump();

 左外联接:就是返回第一个集合的每个元素,而无论该元素在第二个集合中是否具有相关元素。可以使用 LINQ,通过对分组联接的

    结果调用 DefaultIfEmpty 来执行左外部联接。

DefaultIfEmpty:通过使用延迟执行实现。即时返回值为一个对象,该对象存储执行操作所需的所有信息。

它有两个重载方法:1.返回指定序列的元素;如果序列为空,则返回单一实例集合中的类型参数的默认值。

                               2.返回指定序列中的元素;如果序列为空,则返回单一实例集合中的指定值。

(
from c in Customers
from p in c.Purchases.DefaultIfEmpty()
select new { c.Name, p.Description, Price = (decimal?) p.Price }
)
.Dump ("An outer join (without the predicate)");
NameDescriptionPrice

Mary

Boat

30000

Mary

Camera

1200

Bloggs

null null


 

 

 

 

 

from c in Customers
from p in c.Purchases.Where (p => p.Price > 1000).DefaultIfEmpty()
select new
{
c.Name,
p.Description,
Price = (decimal?) p.Price
}
NameDescriptionPrice

Tom

Holiday

2000

Dick

null null   

 

 

 

 

Any:用于判断集合中是否有元素满足某一条件;不延迟。(若条件为空,则集合只要不为空就返回True,否则为False)。

有两个重载方法,分别为简单形式和带条件形式。

from c in Customers
join p in Purchases on c.ID equals p.CustomerID
into custPurchases
where custPurchases.Any()
select new
{
CustName = c.Name,
custPurchases
}

OrderBy

var names = new[] { "Tom", "Dick", "Harry", "Mary", "Jay" }.AsQueryable();

names.OrderBy (s => s.Length).ThenBy (s => s)
.Dump ("By length, then alphabetically");

Group By

from p in Purchases
group p.Price by p.Date.Year into salesByYear
where salesByYear.Average (x => x) > 1000
select new
{
Year = salesByYear.Key,
TotalSales = salesByYear.Count(),
AvgSale = salesByYear.Average(),
TotalValue = salesByYear.Sum()
}

 Concat and Union

int[] seq1 = { 1, 2, 3 }, seq2 = { 3, 4, 5 };

seq1.Concat (seq2).Dump ("Concat");//123345
seq1.Union (seq2).Dump ("Union");//12345

Intersect  and Except   

int[] seq1 = { 1, 2, 3 }, seq2 = { 3, 4, 5 };
seq1.Intersect (seq2).Dump ("Intersect");//3
seq1.Except (seq2).Dump ("seq1.Except (seq2)");//12
seq2.Except (seq1).Dump ("seq2.Except (seq1)");//45

Cast and OfType

classicList.AddRange ( new int[] { 3, 4, 5 } );
DateTime offender = DateTime.Now;
classicList.Add (offender);
IEnumerable<int>
ofTypeSequence = classicList.OfType<int>(),
castSequence = classicList.Cast<int>();
ofTypeSequence.Dump ("Notice that the offending DateTime element is missing");
//Notice what the offending DateTime element does to the Cast sequence
//castSequence.Dump();

Element Operatiors

int[] numbers  = { 1, 2, 3, 4, 5 };
numbers.First().Dump ("First");//1
numbers.Last().Dump ("Last");//5
numbers.FirstOrDefault (n => n > 10).Dump("FirstOrDefault(10)");//0
numbers.ElementAt (2).Dump ("ElementAt (2)");//3
numbers.ElementAtOrDefault (9).Dump ("ElementAtOrDefault (9)");//0
numbers.Single (n => n % 3 == 0).Dump ("The Single number divisible by 3");//3
numbers.SingleOrDefault (n => n > 10).Dump ("The SingleOrDefault number > 10");//0

Aggregation Methods

"pa55w0rd".Count (c => char.IsDigit (c)).Dump ("Count with predicate");//3
int[] numbers = { 28, 32, 14 };
numbers.Min().Dump ("Min");//14
numbers.Max().Dump ("Max");//28
numbers.Sum().Dump ("Sum");//74
numbers.Average().Dump ("Average (mean)");//24.7

Quantifies

new int[] { 2, 3, 4 }.Contains (3)               .Dump ("Contains (3)");//True
new int[] { 2, 3, 4 }.Any (n => n == 3) .Dump ("Any (n => n == 3)");//True
new int[] { 2, 3, 4 }.Any (n => n > 10) .Dump ("Has a big number");//False
new int[] { 2, 3, 4 }.Where (n => n > 10).Any() .Dump ("Has a big number");//False
var query = "Hello".Distinct();
query.SequenceEqual ("Helo").Dump();
Customers.Where (c => c.Purchases.All (p => p.Price < 100))//ALL:用于判断集合中所有元素是否都满足某一条件;不延迟

Generation Methods

Enumerable.Range (5, 5).Dump ("Range"); //56789
Enumerable.Repeat (5, 3).Dump ("Repeat");//555

posted on 2012-03-05 21:56  Sanic  阅读(258)  评论(0编辑  收藏  举报

导航