Aggregate Operators
Count - Simple This determines the number of unique factors of the number 300. The sample starts with the input integer array, uses Distinct to create a sequence with duplicate elements removed, then uses Count on this sequence to determine the number of unique factors.
public void Linq73() { int[] factorsOf300 = { 2, 2, 3, 5, 5 };
int uniqueFactors = factorsOf300.Distinct().Count();
Console.WriteLine("There are {0} unique factors of 300.", uniqueFactors); }
Result There are 3 unique factors of 300.
Count - Conditional This sample finds the number of odd elements of an integer array. The sample passes a lambda expression to Count that it uses to perform the test, while Count handles the iteration and maintains the running total.
public void Linq74() { int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
int oddNumbers = numbers.Count(n => n % 2 == 1);
Console.WriteLine("There are {0} odd numbers in the list.", oddNumbers); }
Result There are 5 odd numbers in the list.
Count - Indexed This sample uses Count to get the number of ints in the array whose value is odd if its position is odd, or whose value is even if its position is even. public void Linq75() { int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
int oddEvenMatches = numbers.Count((n, index) => n % 2 == index % 2);
Console.WriteLine("There are {0} numbers in the list whose odd/even status " + "matches that of their position.", oddEvenMatches); }
Result There are 4 numbers in the list whose odd/even status matches that of their position.
Count - Nested This sample uses Count to return a list of customers and how many orders each has.
public void Linq76() { List customers = GetCustomerList();
var orderCounts = from c in customers select new {c.CustomerID, OrderCount = c.Orders.Count()};
ObjectDumper.Write(orderCounts); }
Result CustomerID=ALFKI OrderCount=6 CustomerID=ANATR OrderCount=4 CustomerID=ANTON OrderCount=7 CustomerID=AROUT OrderCount=13 CustomerID=BERGS OrderCount=18 CustomerID=BLAUS OrderCount=7 CustomerID=BLONP OrderCount=11 CustomerID=BOLID OrderCount=3 CustomerID=BONAP OrderCount=17 CustomerID=BOTTM OrderCount=14 CustomerID=BSBEV OrderCount=10 CustomerID=CACTU OrderCount=6 CustomerID=CENTC OrderCount=1 CustomerID=CHOPS OrderCount=8 CustomerID=COMMI OrderCount=5 CustomerID=CONSH OrderCount=3 CustomerID=DRACD OrderCount=6 CustomerID=DUMON OrderCount=4 CustomerID=EASTC OrderCount=8 CustomerID=ERNSH OrderCount=30 CustomerID=FAMIA OrderCount=7 CustomerID=FISSA OrderCount=0 CustomerID=FOLIG OrderCount=5 CustomerID=FOLKO OrderCount=19 CustomerID=FRANK OrderCount=15 CustomerID=FRANR OrderCount=3 CustomerID=FRANS OrderCount=6 CustomerID=FURIB OrderCount=8 CustomerID=GALED OrderCount=5 CustomerID=GODOS OrderCount=10 CustomerID=GOURL OrderCount=9 CustomerID=GREAL OrderCount=11 CustomerID=GROSR OrderCount=2 CustomerID=HANAR OrderCount=14 CustomerID=HILAA OrderCount=18 CustomerID=HUNGC OrderCount=5 CustomerID=HUNGO OrderCount=19 CustomerID=ISLAT OrderCount=10 CustomerID=KOENE OrderCount=14 CustomerID=LACOR OrderCount=4 CustomerID=LAMAI OrderCount=14 CustomerID=LAUGB OrderCount=3 CustomerID=LAZYK OrderCount=2 CustomerID=LEHMS OrderCount=15 CustomerID=LETSS OrderCount=4 CustomerID=LILAS OrderCount=14 CustomerID=LINOD OrderCount=12 CustomerID=LONEP OrderCount=8 CustomerID=MAGAA OrderCount=10 CustomerID=MAISD OrderCount=7 CustomerID=MEREP OrderCount=13 CustomerID=MORGK OrderCount=5 CustomerID=NORTS OrderCount=3 CustomerID=OCEAN OrderCount=5 CustomerID=OLDWO OrderCount=10 CustomerID=OTTIK OrderCount=9 CustomerID=PARIS OrderCount=0 CustomerID=PERIC OrderCount=6 CustomerID=PICCO OrderCount=10 CustomerID=PRINI OrderCount=6 CustomerID=QUEDE OrderCount=9 CustomerID=QUEEN OrderCount=13 CustomerID=QUICK OrderCount=28 CustomerID=RANCH OrderCount=5 CustomerID=RATTC OrderCount=18 CustomerID=REGGC OrderCount=12 CustomerID=RICAR OrderCount=11 CustomerID=RICSU OrderCount=10 CustomerID=ROMEY OrderCount=5 CustomerID=SANTG OrderCount=6 CustomerID=SAVEA OrderCount=31 CustomerID=SEVES OrderCount=9 CustomerID=SIMOB OrderCount=7 CustomerID=SPECD OrderCount=4 CustomerID=SPLIR OrderCount=9 CustomerID=SUPRD OrderCount=12 CustomerID=THEBI OrderCount=4 CustomerID=THECR OrderCount=3 CustomerID=TOMSP OrderCount=5 CustomerID=TORTU OrderCount=10 CustomerID=TRADH OrderCount=7 CustomerID=TRAIH OrderCount=3 CustomerID=VAFFE OrderCount=11 CustomerID=VICTE OrderCount=10 CustomerID=VINET OrderCount=4 CustomerID=WANDK OrderCount=10 CustomerID=WARTH OrderCount=15 CustomerID=WELLI OrderCount=9 CustomerID=WHITC OrderCount=14 CustomerID=WILMK OrderCount=8 CustomerID=WOLZA OrderCount=7
Count - Grouped This sample prints each category and the number of products in that category. The sample first uses group by to group the products according to their categories. Then it uses select to create an anonymous for each category that contains the category and number of products.
public void Linq77() { List products = GetProductList();
var categoryCounts = from p in products group p by p.Category into g select new {Category = g.Key, ProductCount = g.Group.Count()};
ObjectDumper.Write(categoryCounts); }
Result Category=Beverages ProductCount=12 Category=Condiments ProductCount=12 Category=Produce ProductCount=5 Category=Meat/Poultry ProductCount=6 Category=Seafood ProductCount=12 Category=Dairy Products ProductCount=10 Category=Confections ProductCount=13 Category=Grains/Cereals ProductCount=7
Sum - Simple This sample used Sum to find the total of all of the numbers in an integer array.
public void Linq78() { int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
double numSum = numbers.Sum();
Console.WriteLine("The sum of the numbers is {0}.", numSum); }
Result The sum of the numbers is 45.
Sum - Projection This sample uses Sum to find the total number of characters in all of the words in a string array.
public void Linq79() { string[] words = { "cherry", "apple", "blueberry" };
double totalChars = words.Sum(w => w.Length);
Console.WriteLine("There are a total of {0} characters in these words.", totalChars); }
Result There are a total of 20 characters in these words.
Sum - Grouped This sample prints, for each category, the total number of units in stock for all products in that category. The sample first uses group by to group the products into categories. It then uses Sum on each group to add the number of units in stock for all products.
public static void Linq80() { List<Product> products = GetProductList();
var categories = from p in products group p by p.Category into g select new { Category = g.Key, TotalUnitsInStock = g.Sum(p => p.UnitsInStock) };
ObjectDumper.Write(categories); }
Result Category=Beverages TotalUnitsInStock=559 Category=Condiments TotalUnitsInStock=507 Category=Produce TotalUnitsInStock=100 Category=Meat/Poultry TotalUnitsInStock=165 Category=Seafood TotalUnitsInStock=701 Category=Dairy Products TotalUnitsInStock=393 Category=Confections TotalUnitsInStock=386 Category=Grains/Cereals TotalUnitsInStock=308
Min - Simple This sample uses Min to get the lowest number in an integer array.
public void Linq81() { int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
int minNum = numbers.Min();
Console.WriteLine("The minimum number is {0}.", minNum); }
Result The minimum number is 0.
Min - Projection This sample uses Min to get the length of the shortest word in a string array.
public void Linq82() { string[] words = { "cherry", "apple", "blueberry" };
int shortestWord = words.Min(w => w.Length);
Console.WriteLine("The shortest word is {0} characters long.", shortestWord); }
Result The shortest word is 5 characters long.
Min - Grouped This sample finds, for each category, the lowest of all product prices. The sample uses group by to group the products into categories and select to create a sequence of anonymous objects that contain the Category and the minimum price. The minimum price for each group is found using Min, comparing the UnitPrice for each product.
public void Linq83() { List products = GetProductList();
var categories = from p in products group p by p.Category into g select new {Category = g.Key, CheapestPrice = g.Group.Min(p => p.UnitPrice)};
ObjectDumper.Write(categories); }
Result Category=Beverages CheapestPrice=4.5000 Category=Condiments CheapestPrice=10.0000 Category=Produce CheapestPrice=10.0000 Category=Meat/Poultry CheapestPrice=7.4500 Category=Seafood CheapestPrice=6.0000 Category=Dairy Products CheapestPrice=2.5000 Category=Confections CheapestPrice=9.2000 Category=Grains/Cereals CheapestPrice=7.0000
Min - Elements This sample finds the cheapest products in each category. It first groups the products into categories using group by. Then, for each group of products in a category, it finds the lowest price using Min and then finds all products in the category with the same lowest price.
public void Linq84() { List products = GetProductList();
var categories = from p in products group p by p.Category into g from minPrice = g.Group.Min(p => p.UnitPrice) select new {Category = g.Key, CheapestProducts = g.Group.Where(p => p.UnitPrice == minPrice)};
ObjectDumper.Write(categories, 1); }
Result Category=Beverages CheapestProducts=... CheapestProducts: ProductID=24 ProductName=Guaraná Fantástica Category=Beverages UnitPrice=4.5000 UnitsInStock=20 Category=Condiments CheapestProducts=... CheapestProducts: ProductID=3 ProductName=Aniseed Syrup Category=Condiments UnitPrice=10.0000 UnitsInStock=13 Category=Produce CheapestProducts=... CheapestProducts: ProductID=74 ProductName=Longlife Tofu Category=Produce UnitPrice=10.0000 UnitsInStock=4 Category=Meat/Poultry CheapestProducts=... CheapestProducts: ProductID=54 ProductName=Tourtière Category=Meat/Poultry UnitPrice=7.4500 UnitsInStock=21 Category=Seafood CheapestProducts=... CheapestProducts: ProductID=13 ProductName=Konbu Category=Seafood UnitPrice=6.0000 UnitsInStock=24 Category=Dairy Products CheapestProducts=... CheapestProducts: ProductID=33 ProductName=Geitost Category=Dairy Products UnitPrice=2.5000 UnitsInStock=112 Category=Confections CheapestProducts=... CheapestProducts: ProductID=19 ProductName=Teatime Chocolate Biscuits Category=Confections UnitPrice=9.2000 UnitsInStock=25 Category=Grains/Cereals CheapestProducts=... CheapestProducts: ProductID=52 ProductName=Filo Mix Category=Grains/Cereals UnitPrice=7.0000 UnitsInStock=38
Max - Simple This sample uses Max to get the highest number in an integer array.
public void Linq85() { int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
int maxNum = numbers.Max();
Console.WriteLine("The maximum number is {0}.", maxNum); }
Result The maximum number is 9.
Max - Projection This sample uses Max to get the length of the longest word in a string array.
public void Linq86() { string[] words = { "cherry", "apple", "blueberry" };
int longestLength = words.Max(w => w.Length);
Console.WriteLine("The longest word is {0} characters long.", longestLength); }
Result The longest word is 9 characters long.
Max - Grouped This sample finds the most expensive price in each category. The sample uses group by to group the products into categories. Then it finds the minimum price for each group using Max, comparing the UnitPrice for each product.
public void Linq87() { List products = GetProductList();
var categories = from p in products group p by p.Category into g select new {Category = g.Key, MostExpensivePrice = g.Group.Max(p => p.UnitPrice)};
ObjectDumper.Write(categories); }
Result Category=Beverages MostExpensivePrice=263.5000 Category=Condiments MostExpensivePrice=43.9000 Category=Produce MostExpensivePrice=53.0000 Category=Meat/Poultry MostExpensivePrice=123.7900 Category=Seafood MostExpensivePrice=62.5000 Category=Dairy Products MostExpensivePrice=55.0000 Category=Confections MostExpensivePrice=81.0000 Category=Grains/Cereals MostExpensivePrice=38.0000
Max - Elements This sample finds the most expensive products in each category. The sample uses group by to group the products into categories. Then it finds the minimum price for each group using Max, comparing the UnitPrice for each product. Finally, the sample uses Where to find other products in the group with the same maximum price.
public void Linq88() { List products = GetProductList();
var categories = from p in products group p by p.Category into g from maxPrice = g.Group.Max(p => p.UnitPrice) select new {Category = g.Key, MostExpensiveProducts = g.Group.Where(p => p.UnitPrice == maxPrice)};
ObjectDumper.Write(categories, 1); }
Result Category=Beverages MostExpensiveProducts=... MostExpensiveProducts: ProductID=38 ProductName=Côte de Blaye Category=Beverages UnitPrice=263.5000 UnitsInStock=17 Category=Condiments MostExpensiveProducts=... MostExpensiveProducts: ProductID=63 ProductName=Vegie-spread Category=Condiments UnitPrice=43.9000 UnitsInStock=24 Category=Produce MostExpensiveProducts=... MostExpensiveProducts: ProductID=51 ProductName=Manjimup Dried Apples Category=Produce UnitPrice=53.0000 UnitsInStock=20 Category=Meat/Poultry MostExpensiveProducts=... MostExpensiveProducts: ProductID=29 ProductName=Thüringer Rostbratwurst Category=Meat/Poultry UnitPrice=123.7900 UnitsInStock=0 Category=Seafood MostExpensiveProducts=... MostExpensiveProducts: ProductID=18 ProductName=Carnarvon Tigers Category=Seafood UnitPrice=62.5000 UnitsInStock=42 Category=Dairy Products MostExpensiveProducts=... MostExpensiveProducts: ProductID=59 ProductName=Raclette Courdavault Category=Dairy Products UnitPrice=55.0000 UnitsInStock=79 Category=Confections MostExpensiveProducts=... MostExpensiveProducts: ProductID=20 ProductName=Sir Rodney's Marmalade Category=Confections UnitPrice=81.0000 UnitsInStock=40 Category=Grains/Cereals MostExpensiveProducts=... MostExpensiveProducts: ProductID=56 ProductName=Gnocchi di nonna Alice Category=Grains/Cereals UnitPrice=38.0000 UnitsInStock=21
Average - Simple This sample uses Average to get the average of all values of an integer array.
public void Linq89() { int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
double averageNum = numbers.Average();
Console.WriteLine("The average number is {0}.", averageNum); }
Result The average number is 4.5.
Average - Projection This sample uses Average to get the average length of the words in the string array.
public void Linq90() { string[] words = { "cherry", "apple", "blueberry" };
double averageLength = words.Average(w => w.Length);
Console.WriteLine("The average word length is {0} characters.", averageLength); }
Result The average word length is 6.66666666666667 characters.
Average - Grouped This sample prints the average price of the products in each category. The sample first groups products into categories using group by. Then, for each group, it uses Average to average the UnitPrice values. The select clause creates the resulting sequence of categories and average values.
public void Linq91() { List products = GetProductList();
var categories = from p in products group p by p.Category into g select new {Category = g.Key, AveragePrice = g.Group.Average(p => p.UnitPrice)};
ObjectDumper.Write(categories); }
Result Category=Beverages AveragePrice=37.979166666666666666666666667 Category=Condiments AveragePrice=23.0625 Category=Produce AveragePrice=32.3700 Category=Meat/Poultry AveragePrice=54.006666666666666666666666667 Category=Seafood AveragePrice=20.6825 Category=Dairy Products AveragePrice=28.7300 Category=Confections AveragePrice=25.1600 Category=Grains/Cereals AveragePrice=20.2500
Fold - Simple This sample finds the product of all elements of an array of doubles. The samples uses Fold to create a running product on the array, passing each element in turn to the lambda expression that performs the multiplication.
public void Linq92() { double[] doubles = { 1.7, 2.3, 1.9, 4.1, 2.9 };
double product = doubles.Fold((runningProduct, nextFactor) => runningProduct * nextFactor);
Console.WriteLine("Total product of all numbers: {0}", product); }
Result Total product of all numbers: 88.33081
Fold - Seed This sample subtracts a sequence of integers from a starting value, simulating withdrawls from an account. While there is still cash left in the account, the withdrawal succeeds. The sample uses Fold to pass each withdrawal value in turn to the lambda expression that performs the subtraction.
public void Linq93() { double startBalance = 100.0;
int[] attemptedWithdrawals = { 20, 10, 40, 50, 10, 70, 30 };
double endBalance = attemptedWithdrawals.Fold(startBalance, (balance, nextWithdrawal) => ( (nextWithdrawal <= balance) ? (balance - nextWithdrawal) : balance ) );
Console.WriteLine("Ending balance: {0}", endBalance); }
Result Ending balance: 20 |