Projection Operations
Projection operations transform objects into new forms typically consisting of only properties subsequently used.
It constructs a new type from each object. A property can be projected prior to performing a mathematical function on it. Projection can occur with no change to the original object.
The query operator methods used to perform projection follow: Select and SelectMany. The Select method projects values based on a transform function. It uses the following syntax:
public static IEnumerable<TResult> Select<TSource, TResult>( this IEnumerable<TSource> source, Func<TSource, TResult> selector )
Review an example below:
List<string> terms = new List<string>() { "your", "purple", "fox",
"all", "day", "all", "night" };
var query = from term in terms
select term.Substring(0, 1);
foreach (string q in query)
Console.WriteLine(q);
The SelectMany method projects value sequences based on a transform function which it then forms into a single sequence. It uses the following syntax:
public static IEnumerable<TResult> SelectMany<TSource, TResult>( this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector )
Review an example below:
List<string> lyrics = new List<string>() { "all the critics love you in New York",
"all I wanna do is Dance" };
var query = from lyric in lyrics
from term in lyric.Split(' ')
select term;
foreach (string q in query)
Console.WriteLine(q);
SEPARATING FUNCTION
Both Select and SelectMany yield a result value(s) from source values, however, Select produces a single result for each source value. This results in a collection of elements with the same quantity of elements as its source collection. Compare this to SelectMany yielding one result containing concatenated sub-collections from each source value.
FORMS
Use the select clause to perform a wide variety tasks. Review some of the many ways to use select below:
class SelectExample
{
// class definitions
public class Player
{
public string GivenNm { get; set; }
public string SurNm { get; set; }
public int ID { get; set; }
public List<int> Rankings;
public ContactInfo GetContactInfo(SelectExample app, int id)
{
ContactInfo cInfo =
(from ci in app.contactList
where ci.ID == id
select ci)
.FirstOrDefault();
return cInfo;
}
public override string ToString()
{
return GivenNm + " " + SurNm + ":" + ID;
}
}
public class ContactInfo
{
public int ID { get; set; }
public string Email { get; set; }
public string Mobile { get; set; }
public override string ToString() { return Email + "," + Mobile; }
}
public class RankInfo
{
public double Average { get; set; }
public int ID { get; set; }
}
// primary data source
List<Player> players = new List<Player>()
{
new Player {GivenNm="Mike", SurNm="Smith", ID=111,
Rankings= new List<int>() {110, 132, 145, 99}},
new Player {GivenNm="Stacy", SurNm="Thompson", ID=112,
Rankings= new List<int>() {55, 63, 45, 77}},
new Player {GivenNm="Bernard", SurNm="Wright", ID=113,
Rankings= new List<int>() {71, 84, 75, 99}},
new Player {GivenNm="Jermaine", SurNm="Jackson", ID=114,
Rankings= new List<int>() {70, 88, 89, 90}},
};
// contact info data source
List<ContactInfo> contactList = new List<ContactInfo>()
{
new ContactInfo {ID=111, Email="[email protected]", Mobile="555-505-0101"},
new ContactInfo {ID=112, Email="[email protected]", Mobile="555-505-0248"},
new ContactInfo {ID=113, Email="[email protected]", Mobile="555-505-1440"},
new ContactInfo {ID=114, Email="[email protected]", Mobile="555-505-0231"}
};
static void Main(string[] args)
{
SelectExample app = new SelectExample();
// make a filtered sequence of unmodified Players
IEnumerable<Player> playerQueryOne =
from player in app.players
where player.ID > 111
select player;
Console.WriteLine("First Query: select range_variable");
foreach (Player p in playerQueryOne)
{
Console.WriteLine(p.ToString());
}
// Make a filtered sequence of elements containing
// only one property of each Player.
IEnumerable<String> playerQueryTwo =
from player in app.players
where player.ID > 111
select player.SurNm;
Console.WriteLine("\r\n playerQueryTwo: select range_variable.Property");
foreach (string p in playerQueryTwo)
{
Console.WriteLine(p);
}
// Make a filtered sequence of objects produced by
// a method call on each Player.
IEnumerable<ContactInfo> playerQueryThree =
from player in app.players
where player.ID > 111
select player.GetContactInfo(app, player.ID);
Console.WriteLine("\r\n playerQueryThree: select range_variable.Method");
foreach (ContactInfo ci in playerQueryThree)
{
Console.WriteLine(ci.ToString());
}
// Make a filtered sequence of ints from
// the internal array inside each Player.
IEnumerable<int> playerQueryFour =
from player in app.players
where player.ID > 111
select player.Rankings[0];
Console.WriteLine("\r\n playerQueryFour: select range_variable[index]");
foreach (int i in playerQueryFour)
{
Console.WriteLine("1st rank = {0}", i);
}
// Make a filtered sequence of doubles;
// the expression result.
IEnumerable<double> playerQueryFive =
from player in app.players
where player.ID > 111
select player.Rankings[0] * 1.1;
Console.WriteLine("\r\n playerQueryFive: select expression");
foreach (double d in playerQueryFive)
{
Console.WriteLine("Adjusted 1st ranking = {0}", d);
}
// Produce a filtered sequence of doubles that are
// the result of a method call.
IEnumerable<double> playerQuerySix =
from player in app.players
where player.ID > 111
select player.Rankings.Average();
Console.WriteLine("\r\n playerQuerySix: select expression2");
foreach (double d in playerQuerySix)
{
Console.WriteLine("Average = {0}", d);
}
// Make a filtered sequence of anonymous types
// containing only two properties from each Player.
var playerQuerySeven =
from player in app.players
where player.ID > 111
select new { player.GivenNm, player.SurNm };
Console.WriteLine("\r\n playerQuerySeven: select new anonymous type");
foreach (var item in playerQuerySeven)
{
Console.WriteLine("{0}, {1}", item.SurNm, item.GivenNm);
}
// Make a filtered sequence of named objects containing
// a method return value and a property from each Player.
IEnumerable<RankInfo> playerQueryEight =
from player in app.players
where player.ID > 111
select new RankInfo
{
Average = player.Rankings.Average(),
ID = player.ID
};
Console.WriteLine("\r\n playerQueryEight: select new named type");
foreach (RankInfo ri in playerQueryEight)
{
Console.WriteLine("ID = {0}, Average = {1}", ri.ID, ri.Average);
}
// Make a filtered sequence of players from a contact list
// and who average over 60.
IEnumerable<ContactInfo> playerQueryNine =
from player in app.players
where player.Rankings.Average() > 60
join ci in app.contactList on player.ID equals ci.ID
select ci;
Console.WriteLine("\r\n playerQueryNine: select result of join clause");
foreach (ContactInfo ci in playerQueryNine)
{
Console.WriteLine("ID = {0}, Email = {1}", ci.ID, ci.Email);
}
Console.WriteLine("Press a key to continue.");
Console.ReadKey();
}
}