Tải bản đầy đủ - 0 (trang)
16-9. Group Result Elements by Attribute

16-9. Group Result Elements by Attribute

Tải bản đầy đủ - 0trang

CHAPTER 16 ■ USING LINQ



in the data source. The easiest way to understand these keywords is to review and run the example

program that follows.

You can get the value that the elements contained in an IGrouping<> share by calling the Key

property. IGrouping<> extends IEnumerable<>, so you can enumerate the values of a group using a

foreach loop or use an IGrouping<> as the data source for a LINQ query.

You can access each individual group as it is created by LINQ using the order...by...into...

keywords. The addition of into allows you to define a variable that will contain the IGrouping<>

instance—see the example program for this recipe to see an example of using into to create an

anonymous type.



The Code

The following example uses a collection of the type Fruit as the data source for two LINQ queries. The

first uses a standard group...by... format to create an IEnumerable> result,

which is then enumerated by group and the elements in each group. The second query uses

group...by...into... in order to create an anonymous type containing the Key value of the group and

the set of matching Fruit instances, which are then printed out.

using

using

using

using



System;

System.Collections.Generic;

System.Linq;

System.Text;



namespace Apress.VisualCSharpRecipes.Chapter16

{

class Recipe16_09

{

static void Main(string[] args)

{

// Create the data source.

IList datasource = createData();

Console.WriteLine("Perfoming group...by... query");

// Perform a query with a basic grouping.

IEnumerable> result =

from e in datasource group e by e.Color;

foreach (IGrouping group in result)

{

Console.WriteLine("\nStart of group for {0}", group.Key);

foreach (Fruit fruit in group)

{

Console.WriteLine("Name: {0} Color: {1} Shelf Life: {2} days.",

fruit.Name, fruit.Color, fruit.ShelfLife);

}

}



770



www.it-ebooks.info



CHAPTER 16 ■ USING LINQ



Console.WriteLine("\n\nPerfoming group...by...into query");

// Use the group...by...into... keywords.

var result2 = from e in datasource

group e by e.Color into g

select new

{

Color = g.Key,

Fruits = g

};

foreach (var element in result2)

{

Console.WriteLine("\nElement for color {0}", element.Color);

foreach (var fruit in element.Fruits)

{

Console.WriteLine("Name: {0} Color: {1} Shelf Life: {2} days.",

fruit.Name, fruit.Color, fruit.ShelfLife);

}

}

// Wait to continue.

Console.WriteLine("\nMain method complete. Press Enter");

Console.ReadLine();

}

static IList createData()

{

return new List()

{

new Fruit("apple", "green", 7),

new Fruit("orange", "orange", 10),

new Fruit("grape", "green", 4),

new Fruit("fig", "brown", 12),

new Fruit("plum", "red", 2),

new Fruit("banana", "yellow", 10),

new Fruit("cherry", "red", 7)

};

}

}

class Fruit

{

public Fruit(string namearg, string colorarg, int lifearg)

{

Name = namearg;

Color = colorarg;

ShelfLife = lifearg;

}



771



www.it-ebooks.info



CHAPTER 16 ■ USING LINQ



public string Name { get; set; }

public string Color { get; set; }

public int ShelfLife { get; set; }

}

}

Running the example program produces the following results:

Perfoming order...by... query



Start of group for green

Name: apple Color: green Shelf Life: 7 days.

Name: grape Color: green Shelf Life: 4 days.



Start of group for orange

Name: orange Color: orange Shelf Life: 10 days.



Start of group for brown

Name: fig Color: brown Shelf Life: 12 days.



Start of group for red

Name: plum Color: red Shelf Life: 2 days.

Name: cherry Color: red Shelf Life: 7 days.



772



www.it-ebooks.info



CHAPTER 16 ■ USING LINQ



Start of group for yellow

Name: banana Color: yellow Shelf Life: 10 days.



Perfoming order...by...into query



Element for color green

Name: apple Color: green Shelf Life: 7 days.

Name: grape Color: green Shelf Life: 4 days.



Element for color orange

Name: orange Color: orange Shelf Life: 10 days.



Element for color brown

Name: fig Color: brown Shelf Life: 12 days.



Element for color red

Name: plum Color: red Shelf Life: 2 days.

Name: cherry Color: red Shelf Life: 7 days.



Element for color yellow

Name: banana Color: yellow Shelf Life: 10 days.



Main method complete. Press Enter



773



www.it-ebooks.info



CHAPTER 16 ■ USING LINQ



16-10. Sort Query Results

Problem

You need to sort the results of a LINQ query.



Solution

Use the orderby keyword.



How It Works

The orderby keyword sorts the result elements of a LINQ query by the member you specify. You can sort

on several members by using the orderby keyword more than once—see the example code for this recipe

for an illustration. By default, LINQ will sort the elements in ascending order (the smallest value will

come first in the results)—you can use the descending keyword after the member you want to use for

sorting to get the reverse effect.



The Code

The following example creates a collection containing the Fruit type and uses it as the basis for a LINQ

query that orders the results by the Color property in descending order and then the Name property in

ascending order.

using

using

using

using



System;

System.Collections.Generic;

System.Linq;

System.Text;



namespace Apress.VisualCSharpRecipes.Chapter16

{

class Recipe16_10

{

static void Main(string[] args)

{

// Create the data source.

IList datasource = createData();

IEnumerable result = from e in datasource

orderby e.Name

orderby e.Color descending

select e;

foreach (Fruit fruit in result)

{



774



www.it-ebooks.info



CHAPTER 16 ■ USING LINQ



Console.WriteLine("Name: {0} Color: {1} Shelf Life: {2} days.",

fruit.Name, fruit.Color, fruit.ShelfLife);

}

// Wait to continue.

Console.WriteLine("\nMain method complete. Press Enter");

Console.ReadLine();

}

static IList createData()

{

return new List()

{

new Fruit("apple", "red", 7),

new Fruit("apple", "green", 7),

new Fruit("orange", "orange", 10),

new Fruit("grape", "green", 4),

new Fruit("fig", "brown", 12),

new Fruit("plum", "red", 2),

new Fruit("banana", "yellow", 10),

new Fruit("cherry", "red", 7)

};

}

}

class Fruit

{

public Fruit(string namearg, string colorarg, int lifearg)

{

Name = namearg;

Color = colorarg;

ShelfLife = lifearg;

}

public string Name { get; set; }

public string Color { get; set; }

public int ShelfLife { get; set; }

}

}

Running the program gives the following results:

Name: apple Color: red Shelf Life: 7 days.

Name: apple Color: green Shelf Life: 7 days.

Name: banana Color: yellow Shelf Life: 10 days.

Name: cherry Color: red Shelf Life: 7 days.

Name: fig Color: brown Shelf Life: 12 days.



775



www.it-ebooks.info



CHAPTER 16 ■ USING LINQ



Name: grape Color: green Shelf Life: 4 days.

Name: orange Color: orange Shelf Life: 10 days.

Name: plum Color: red Shelf Life: 2 days.



Main method complete. Press Enter



16-11. Compare Data Sources

Problem

You need to determine whether two data sources contain the same elements.



The Solution

Use the SequenceEquals<> extension method.



How It Works

The SequenceEquals<> extension method compares two data sources and returns true if both data

sources contain the same number of elements and the individual elements in each position in each data

source are the same. You can specify your own code to assess element equality by implementing the

System.Collections.Generic.IEqualityComparer<> interface and supplying an instance of the

implementation as an argument to SequenceEquals<>.



The Code

The following example creates four data sources. The first contains a list of names of fruit. The second

contains the same names in the same order. The third contains the same names in a different order, and

the last contains different names, but with the same first letters as the names in the first list.

Comparisons are then performed using the default IEqualityComparer and a custom IEqualityComparer

that treats strings with the same first character as being equal.

using

using

using

using



System;

System.Collections.Generic;

System.Linq;

System.Text;



776



www.it-ebooks.info



CHAPTER 16 ■ USING LINQ



namespace Apress.VisualCSharpRecipes.Chapter16

{

class Recipe16_11

{

static void Main(string[] args)

{

// Create the first data source.

string[] ds1 = { "apple", "cherry", "pear" };

// Create a data source with the same elements

// in the same order.

string[] ds2 = { "apple", "cherry", "pear" };

// Create a data source with the

// same elements in a different order.

string[] ds3 = { "pear", "cherry", "apple" };

// Create a data source with different elements.

string[] ds4 = { "apricot", "cranberry", "plum" };

// Perform the comparisons.

Console.WriteLine("Using standard comparer");

Console.WriteLine("DS1 == DS2? {0}", ds1.SequenceEqual(ds2));

Console.WriteLine("DS1 == DS3? {0}", ds1.SequenceEqual(ds3));

Console.WriteLine("DS1 == DS4? {0}", ds1.SequenceEqual(ds4));

// Create the custom comparer.

MyComparer comparer = new MyComparer();

Console.WriteLine("\nUsing custom comparer");

Console.WriteLine("DS1 == DS2? {0}", ds1.SequenceEqual(ds2, comparer));

Console.WriteLine("DS1 == DS3? {0}", ds1.SequenceEqual(ds3, comparer));

Console.WriteLine("DS1 == DS4? {0}", ds1.SequenceEqual(ds4, comparer));

// Wait to continue.

Console.WriteLine("\nMain method complete. Press Enter");

Console.ReadLine();

}

}

class MyComparer : IEqualityComparer

{

public bool Equals(string first, string second)

{

return first[0] == second[0];

}

public int GetHashCode(string str)

{

return str[0].GetHashCode();

}

}

}



777



www.it-ebooks.info



CHAPTER 16 ■ USING LINQ



Running the program gives the following results:

Using standard comparer

DS1 == DS2? True

DS1 == DS3? False

DS1 == DS4? False



Using custom comparer

DS1 == DS2? True

DS1 == DS3? False

DS1 == DS4? True



Main method complete. Press Enter



16-12. Aggregate Data Sources

Problem

You need to aggregate the values in a data source.



Solution

Use the Average<>, Count<>, Max<>, Min<>, or Sum<> extension methods for standard aggregations, or the

Aggregate<> extension method to perform a custom aggregation.



How It Works

The standard aggregation extension methods process the elements in a data source to perform useful

calculations. Average<> calculates the mean value, Count<> returns the number of elements in the data

source, Min<> and Max<> return the smallest and largest elements, and Sum<> totals the elements.

You can perform custom aggregation operations using the Aggregate<> method. The example code

demonstrates two custom aggregation operations. The expression receives two arguments—the first is



778



www.it-ebooks.info



CHAPTER 16 ■ USING LINQ



the aggregate value so far and the second is the current element to process. The parameters and

return value are of the same type as the data source type—that is, if you are aggregating an

IEnumeration, you will receive two strings as arguments and must return a string as your

aggregate result.



The Code

The following example creates a data source of integers and calls each of the standard aggregation

methods. The same data source is used to demonstrate a custom aggregation method that totals the

individual elements (equivalent to the Sum<> method). Finally, a string array is used as a data source for

a custom aggregation that concatenates the individual elements.

using

using

using

using



System;

System.Collections.Generic;

System.Linq;

System.Text;



namespace Apress.VisualCSharpRecipes.Chapter16

{

class Recipe16_12

{

static void Main(string[] args)

{

// Define a numeric data source.

int[] ds1 = { 1, 23, 37, 49, 143 };

// Use the standard aggregation methods.

Console.WriteLine("Standard aggregation methods");

Console.WriteLine("Average: {0}", ds1.Average());

Console.WriteLine("Count: {0}", ds1.Count());

Console.WriteLine("Max: {0}", ds1.Max());

Console.WriteLine("Min: {0}", ds1.Min());

Console.WriteLine("Sum: {0}", ds1.Sum());

// Perform our own sum aggregation.

Console.WriteLine("\nCustom aggregation");

Console.WriteLine(ds1.Aggregate((total, elem) => total += elem));

// Define a string data source.

string[] ds2 = { "apple", "pear", "cherry" };

// Perform a concat aggregation.

Console.WriteLine("\nString concatenation aggregation");

Console.WriteLine(ds2.Aggregate((len, elem) => len += elem));



779



www.it-ebooks.info



CHAPTER 16 ■ USING LINQ



// Wait to continue.

Console.WriteLine("\nMain method complete. Press Enter");

Console.ReadLine();

}

}

}

The program gives the following results:

Standard aggregation methods

Average: 50.6

Count: 5

Max: 143

Min: 1

Sum: 253



Custom aggregation

253



String concatenation aggregation

applepearcherry



Main method complete. Press Enter



16-13. Share Values Within a Query

Problem

You need to perform an operation on an element or a data source only once in a query.



780



www.it-ebooks.info



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

16-9. Group Result Elements by Attribute

Tải bản đầy đủ ngay(0 tr)

×