LINQ Aggregator Operators (집계연산자)

2022. 2. 9. 00:00CSharp/Advance

반응형

시퀀스의 값에 대해 계산을 수행하는 방법

Count

// 중복되는 값을 제거하고 counting
int[] factorsOf300 = { 2, 2, 3, 5, 5 };
int uniqueFactors = factorsOf300.Distinct().Count();
Console.WriteLine($"There are {uniqueFactors} unique factors of 300.");
// output
There are 3 unique factors of 300.

// 2로 나눈 나머지가 1인것 찾기 (홀수)
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);
// output
There are 5 odd numbers in the list.

// 내부 속성의 count
List<Customer> customers = GetCustomerList();
var orderCounts = from c in customers
                  select (c.CustomerID, OrderCount: c.Orders.Count());
foreach (var customer in orderCounts)
{
    Console.WriteLine($"ID: {customer.CustomerID}, count: {customer.OrderCount}");
}
// output
...
ID: TRADH, count: 7
ID: TRAIH, count: 3
ID: VAFFE, count: 11
ID: VICTE, count: 10
ID: VINET, count: 4
ID: WANDK, count: 10
ID: WARTH, count: 15
ID: WELLI, count: 9
ID: WHITC, count: 14
ID: WILMK, count: 8
ID: WOLZA, count: 7


// grouping 후 count
List<Product> products = GetProductList();
// category 별로 product 를 그룹핑 하고 해당 group 의 product count 계산
var categoryCounts = from p in products
                     group p by p.Category into g
                     select (Category: g.Key, ProductCount: g.Count());
foreach (var c in categoryCounts)
{
    Console.WriteLine($"Category: {c.Category}: Product count: {c.ProductCount}");
}
// output
Category: Beverages: Product count: 12
Category: Condiments: Product count: 12
Category: Produce: Product count: 5
Category: Meat/Poultry: Product count: 6
Category: Seafood: Product count: 12
Category: Dairy Products: Product count: 10
Category: Confections: Product count: 13
Category: Grains/Cereals: Product count: 7

합산 (Sum)

// 기본 sum
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
double numSum = numbers.Sum();
Console.WriteLine($"The sum of the numbers is {numSum}");
// output
The sum of the numbers is 45

// Projection Sum
string[] words = { "cherry", "apple", "blueberry" };
double totalChars = words.Sum(w => w.Length);
Console.WriteLine($"There are a total of {totalChars} characters in these words.");
// output
There are a total of 20 characters in these words.

// Group Sum
List<Product> products = GetProductList();
var categories = from p in products
                 group p by p.Category into g
                 select (Category: g.Key, TotalUnitsInStock: g.Sum(p => p.UnitsInStock));
foreach (var pair in categories)
{
    Console.WriteLine($"Category: {pair.Category}, Units in stock: {pair.TotalUnitsInStock}");
}
// output
Category: Beverages, Units in stock: 559
Category: Condiments, Units in stock: 507
Category: Produce, Units in stock: 100
Category: Meat/Poultry, Units in stock: 165
Category: Seafood, Units in stock: 701
Category: Dairy Products, Units in stock: 393
Category: Confections, Units in stock: 386
Category: Grains/Cereals, Units in stock: 308

최소 (Min)

// 기본 최소값
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
int minNum = numbers.Min();
Console.WriteLine($"The minimum number is {minNum}");
// output
The minimum number is 0

// group 별 최소값 
List<Product> products = GetProductList();
var categories = from p in products
                 group p by p.Category into g
                 select (Category: g.Key, CheapestPrice: g.Min(p => p.UnitPrice));
foreach (var c in categories)
{
    Console.WriteLine($"Category: {c.Category}, Lowest price: {c.CheapestPrice}");
}
// output
Category: Beverages, Lowest price: 4.5000
Category: Condiments, Lowest price: 10.0000
Category: Produce, Lowest price: 10.0000
Category: Meat/Poultry, Lowest price: 7.4500
Category: Seafood, Lowest price: 6.0000
Category: Dairy Products, Lowest price: 2.5000
Category: Confections, Lowest price: 9.2000
Category: Grains/Cereals, Lowest price: 7.0000

// group 별 최소값을 갖는 모든 item 찾기
List<Product> products = GetProductList();
var categories = from p in products
                 group p by p.Category into g
                 let minPrice = g.Min(p => p.UnitPrice)
                 select (Category: g.Key, CheapestProducts: g.Where(p => p.UnitPrice == minPrice));
foreach (var c in categories)
{
    Console.WriteLine($"Category: {c.Category}");
    foreach (var p in c.CheapestProducts)
    {
        Console.WriteLine($"\tProduct: {p}");
    }
}
// output
Category: Beverages
        Product: ProductID=24 ProductName=Guarana Fantastica Category=Beverages UnitPrice=$4.50 UnitsInStock=20
Category: Condiments
        Product: ProductID=3 ProductName=Aniseed Syrup Category=Condiments UnitPrice=$10.00 UnitsInStock=13
Category: Produce
        Product: ProductID=74 ProductName=Longlife Tofu Category=Produce UnitPrice=$10.00 UnitsInStock=4
Category: Meat/Poultry
        Product: ProductID=54 ProductName=Tourtiere Category=Meat/Poultry UnitPrice=$7.45 UnitsInStock=21
Category: Seafood
        Product: ProductID=13 ProductName=Konbu Category=Seafood UnitPrice=$6.00 UnitsInStock=24
Category: Dairy Products
        Product: ProductID=33 ProductName=Geitost Category=Dairy Products UnitPrice=$2.50 UnitsInStock=112
Category: Confections
        Product: ProductID=19 ProductName=Teatime Chocolate Biscuits Category=Confections UnitPrice=$9.20 UnitsInStock=25
Category: Grains/Cereals
        Product: ProductID=52 ProductName=Filo Mix Category=Grains/Cereals UnitPrice=$7.00 UnitsInStock=38

최대 (Max)

int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
int maxNum = numbers.Max();
Console.WriteLine($"The maximum number is {maxNum}");
// output
The maximum number is 9

// 나머지는 Min 과 똑같이 사용 가능하다.

평균 (Average)

// 기본
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
double averageNum = numbers.Average();
Console.WriteLine($"The average number is {averageNum}.");
// output
The average number is 4.5.

// group 별 평균
List<Product> products = GetProductList();
var categories = from p in products
                 group p by p.Category into g
                 select (Category: g.Key, AveragePrice: g.Average(p => p.UnitPrice));
foreach (var c in categories)
{
    Console.WriteLine($"Category: {c.Category}, Average price: {c.AveragePrice}");
}
// output
Category: Beverages, Average price: 37.979166666666666666666666667
Category: Condiments, Average price: 23.0625
Category: Produce, Average price: 32.3700
Category: Meat/Poultry, Average price: 54.006666666666666666666666667
Category: Seafood, Average price: 20.6825
Category: Dairy Products, Average price: 28.7300
Category: Confections, Average price: 25.1600
Category: Grains/Cereals, Average price: 20.2500

 

Aggregate

이전에 수행 한 작업을 고려하여 목록의 각 요소에 대해 작업을 수행한다.

즉, 첫 번째 요소와 두 번째 요소에 대해 작업을 수행하고 결과를 전달

그런 다음 이전 결과와 세 번째 요소에서 작업을 계속 진행

// 기본 (합산을 하도록 func 을 구성함)
double[] doubles = { 1.5, 2.5, 3.5, -1.5, -2.5 };
double product = doubles.Aggregate((runningProduct, nextFactor) => runningProduct + nextFactor);
Console.WriteLine($"Total sum of all numbers: {product}");
// output
Total sum of all numbers: 3.5

// seed 값을 기준으로 aggregate (잔액을 계산하도록 구성)
double startBalance = 100.0;
int[] attemptedWithdrawals = { 20, 10, 40, 50, 10, 70, 30 };
double endBalance =
    attemptedWithdrawals.Aggregate(startBalance,
        (balance, nextWithdrawal) =>
            ((nextWithdrawal <= balance) ? (balance - nextWithdrawal) : balance));
// output
Ending balance: 20

 

관련영상

https://youtu.be/gHzqrwCOvc0

 

반응형