LINQ Aggregate 알고리즘 설명


721

이것은 절름발이 들릴지 모르지만에 대한 좋은 설명을 찾지 못했습니다 Aggregate.

좋은 것은 작고 명확한 예와 함께 짧고 설명 적이며 포괄적이라는 것을 의미합니다.

답변:


1015

가장 이해하기 쉬운 정의 Aggregate는 이전에 수행 한 작업을 고려하여 목록의 각 요소에 대해 작업을 수행한다는 것입니다. 즉, 첫 번째 요소와 두 번째 요소에 대해 작업을 수행하고 결과를 전달합니다. 그런 다음 이전 결과와 세 번째 요소에서 작동하여 계속 진행됩니다. 기타

예 1. 숫자 합산

var nums = new[]{1,2,3,4};
var sum = nums.Aggregate( (a,b) => a + b);
Console.WriteLine(sum); // output: 10 (1+2+3+4)

이 추가 1하고 2만들 수 3있습니다. 그런 다음 3(이전 결과) 및 3(다음 요소 순서대로)를 추가하여 만듭니다 6. 그런 다음 6and 4을 추가합니다 10.

예제 2. 문자열 배열에서 csv 만들기

var chars = new []{"a","b","c", "d"};
var csv = chars.Aggregate( (a,b) => a + ',' + b);
Console.WriteLine(csv); // Output a,b,c,d

이것은 거의 같은 방식으로 작동합니다. a쉼표를 연결 하고 b만드십시오 a,b. 그런 다음 a,b 쉼표로 연결하고을 c만듭니다 a,b,c. 등등.

예 3. 시드를 사용하여 숫자 곱하기

완전성 들어있다 과부하Aggregate시드 값을 취한다.

var multipliers = new []{10,20,30,40};
var multiplied = multipliers.Aggregate(5, (a,b) => a * b);
Console.WriteLine(multiplied); //Output 1200000 ((((5*10)*20)*30)*40)

위의 예 5와 마찬가지로이 값은 값으로 시작 하여 시퀀스의 첫 번째 요소에 곱하여 10결과를 제공합니다 50. 이 결과는 다음의 숫자로 이월되어 승산되어 20결과를 제공합니다 1000. 이것은 시퀀스의 나머지 2 요소를 통해 계속됩니다.

실제 예 : http://rextester.com/ZXZ64749
문서 : http://msdn.microsoft.com/en-us/library/bb548651.aspx


추가

위의 예 2에서는 문자열 연결을 사용하여 쉼표로 구분 된 값 목록을 만듭니다. 이것은 Aggregate이 답변의 의도 인 사용법을 설명하는 간단한 방법 입니다. 그러나이 기술을 사용하여 실제로 쉼표로 구분 된 대량의 데이터를 작성하는 경우을 사용하는 것이 더 적합 하며 시드 과부하를 사용하여을 시작하는 것과 StringBuilder완전히 호환됩니다 .AggregateStringBuilder

var chars = new []{"a","b","c", "d"};
var csv = chars.Aggregate(new StringBuilder(), (a,b) => {
    if(a.Length>0)
        a.Append(",");
    a.Append(b);
    return a;
});
Console.WriteLine(csv);

업데이트 된 예 : http://rextester.com/YZCVXV6464


11
첫 번째 설명에 대한 또 다른 설명은 사용자가 제공하는 함수가 배열이 하나의 요소로 축소 될 때까지 항상 처음 두 멤버를 결합한다는 것입니다. 그래서 [1,2,3,4]할 것이다 [3,3,4]다음 [6,4]마지막에 [10]. 그러나 단일 값의 배열을 반환하는 대신 값 자체를 얻습니다.
David Raab

2
집계 함수에서 조기 중단 / 종료 할 수 있습니까? 예를 들어, chars.Aggregate ((a, b) => {if (a == 'a')는 전체 집계를 끊고 그렇지 않으면 a + ','+ b}를 반환합니다.
Jeff Tian

13
@JeffTian - 나는 체인 제안 TakeWhileAggregateEnumerable에서 확장의 beatuty 그게 전부 - - 그들은 쉽게 체인 가능합니다. 그래서 당신은 결국 TakeWhile(a => a == 'a').Aggregate(....). 이 예를 참조하십시오 : rextester.com/WPRA60543
Jamiec

2
부록에 대한 주석으로 전체 블록을 쉽게 대체 할 수 있습니다 var csv = string.Join(",", chars)(집계 또는 stringbuilders가 필요 없음). 그렇습니다. 응답의 요점은 집계의 사용 예를 제시하여 멋지다는 것을 알고 있습니다. 그러나 나는 여전히 문자열을 결합하는 것이 권장되지 않는다고 언급하고 싶었습니다. 이미 전용 메소드가 있습니다 ....
T_D

2
또 다른 일반적인 사용법 (지금까지 생산 코드에서 보았던 유일한 것)은 다음과 같은 최소 또는 최대 항목을 얻는 것입니다.var biggestAccount = Accounts.Aggregate((a1, a2) => a1.Amount >= a2.Amount ? a1 : a2);
Franck

133

어떤 오버로드에 대해 부분적으로 의존하지만 기본 아이디어는 다음과 같습니다.

  • "현재 값"으로 시드로 시작
  • 시퀀스를 반복합니다. 시퀀스의 각 값에 대해 :
    • 변환 할 수있는 사용자 지정 기능 적용 (currentValue, sequenceValue)으로를(nextValue)
    • 세트 currentValue = nextValue
  • 최종 반환 currentValue

Aggregate내 Edulinq 시리즈게시물이 유용하다는 것을 알 수 있습니다. 자세한 내용 (다양한 과부하 포함)과 구현이 포함되어 있습니다.

하나의 간단한 예는 다음에 Aggregate대한 대안으로 사용 하는 것입니다 Count.

// 0 is the seed, and for each item, we effectively increment the current value.
// In this case we can ignore "item" itself.
int count = sequence.Aggregate(0, (current, item) => current + 1);

또는 일련의 문자열에서 모든 문자열 길이를 합산하십시오.

int total = sequence.Aggregate(0, (current, item) => current + item.Length);

개인적으로 나는 거의 찾을 수없는 Aggregate유용한 -은 "맞춤형"집계 방법은 나를 위해 일반적으로 충분하다.


6
@Jon 항목을 트리로 분할하여 작업을 코어간에 분할 할 수있는 비동기식 변형 집합이 있습니까? 이 방법의 디자인은 "감소"또는 "접기"의 개념과 일치하는 것 같지만, 실제로 그것이 실제로 수행되고 있는지 또는 단순히 항목 목록을 반복하는지 여부는 알 수 없습니다.
AaronLS

@ Jon : 위에서 언급 한 edulink가 작동하지 않습니다. 올바른 링크로 리디렉션 할 수 있습니까? 답변에 사용한 "맞춤형"집계 함수라는 용어에 대해보다 구체적으로 설명해 주시겠습니까?
Koushik

1
@ Koousik : 게시물의 링크를 수정했습니다. "맞춤형"집계 함수는 Max / Min / Count / Sum과 같은 것을 의미합니다.
Jon Skeet

62

Super short Aggregate는 Haskell / ML / F #에서 접기처럼 작동합니다.

약간 더 긴 .Max (), .Min (), .Sum (), .Average ()는 모든 요소를 ​​순서대로 반복하고 각 집계 함수를 사용하여 집계합니다. .Aggregate ()는 개발자가 시작 상태 (일명 시드)와 집계 함수를 지정할 수 있다는 점에서 일반화 된 집계 자입니다.

나는 당신이 짧은 설명을 요구했다는 것을 알고 있지만 다른 사람들이 짧은 대답을 몇 개 주었을 때 약간 더 긴 것에 관심이 있다고 생각했습니다.

코드가있는 긴 버전 foreach를 사용하고 .Aggregate를 사용하여 한 번 샘플 표준 편차 를 구현하는 방법을 보여줄 수있는 한 가지 방법이 있습니다 . 참고 : 나는 여기서 성능 우선 순위를 정하지 않았으므로 불필요하게 colleciton을 여러 번 반복합니다.

먼저 이차 거리의 합을 만드는 데 사용되는 도우미 함수 :

static double SumOfQuadraticDistance (double average, int value, double state)
{
    var diff = (value - average);
    return state + diff * diff;
}

그런 다음 ForEach를 사용하여 표준 편차를 샘플링하십시오.

static double SampleStandardDeviation_ForEach (
    this IEnumerable<int> ints)
{
    var length = ints.Count ();
    if (length < 2)
    {
        return 0.0;
    }

    const double seed = 0.0;
    var average = ints.Average ();

    var state = seed;
    foreach (var value in ints)
    {
        state = SumOfQuadraticDistance (average, value, state);
    }
    var sumOfQuadraticDistance = state;

    return Math.Sqrt (sumOfQuadraticDistance / (length - 1));
}

그런 다음 .Aggregate를 사용하여 한 번 :

static double SampleStandardDeviation_Aggregate (
    this IEnumerable<int> ints)
{
    var length = ints.Count ();
    if (length < 2)
    {
        return 0.0;
    }

    const double seed = 0.0;
    var average = ints.Average ();

    var sumOfQuadraticDistance = ints
        .Aggregate (
            seed,
            (state, value) => SumOfQuadraticDistance (average, value, state)
            );

    return Math.Sqrt (sumOfQuadraticDistance / (length - 1));
}

sumOfQuadraticDistance가 계산되는 방식을 제외하고 이러한 함수는 동일합니다.

var state = seed;
foreach (var value in ints)
{
    state = SumOfQuadraticDistance (average, value, state);
}
var sumOfQuadraticDistance = state;

대:

var sumOfQuadraticDistance = ints
    .Aggregate (
        seed,
        (state, value) => SumOfQuadraticDistance (average, value, state)
        );

따라서 .Aggregate 가하는 것은이 집계 자 패턴을 캡슐화하고 .Aggregate의 구현이 다음과 같이 보일 것으로 기대합니다.

public static TAggregate Aggregate<TAggregate, TValue> (
    this IEnumerable<TValue> values,
    TAggregate seed,
    Func<TAggregate, TValue, TAggregate> aggregator
    )
{
    var state = seed;

    foreach (var value in values)
    {
        state = aggregator (state, value);
    }

    return state;
}

표준 편차 함수를 사용하면 다음과 같습니다.

var ints = new[] {3, 1, 4, 1, 5, 9, 2, 6, 5, 4};
var average = ints.Average ();
var sampleStandardDeviation = ints.SampleStandardDeviation_Aggregate ();
var sampleStandardDeviation2 = ints.SampleStandardDeviation_ForEach ();

Console.WriteLine (average);
Console.WriteLine (sampleStandardDeviation);
Console.WriteLine (sampleStandardDeviation2);

이모

그렇다면 .Aggregate는 가독성에 도움이됩니까? 일반적으로 나는 .LINQ를 좋아합니다. 완전성 때문에 집계가 Linq에 있어야하지만 개인적으로 그렇게 확신하지는 않습니다. 집계는 잘 작성된 foreach에 비해 가독성을 추가합니다.


+1 우수! 그러나 확장 방법 SampleStandardDeviation_Aggregate()SampleStandardDeviation_ForEach()수 없습니다 private그래서 중 하나에 의해 발생되어 있어야합니다 (액세스 한정자의 부재에서 기본적으로) public또는 internal, 그것은 나에게 보인다
Fulproof

참고 : 샘플의 확장 메소드가 올바르게 기억되면이 경우 ==> 개인 작업을 사용한 것과 동일한 클래스의 일부였습니다.
또 다른 메타 프로그래머

39

그림은 천 단어의 가치가 있습니다

알림 :
Func<X, Y, R>유형 X및의 입력이 두 개인 함수이며 유형 Y의 결과를 반환합니다 R.

집계 가능 : 집계에는 세 가지 과부하가 있습니다.


과부하 1 :

A Aggregate<A>(IEnumerable<A> a, Func<A, A, A> f)

집계 1

예:

new[]{1,2,3,4}.Aggregate((x, y) => x + y);  // 10


이 과부하는 간단하지만 다음과 같은 제한이 있습니다.

  • 시퀀스에는 적어도 하나의 요소가 포함되어야합니다.
    그렇지 않으면 함수가를 발생 InvalidOperationException시킵니다.
  • 요소와 결과는 동일한 유형이어야합니다.



과부하 2 :

B Aggregate<A, B>(IEnumerable<A> a, B bIn, Func<B, A, B> f)

집계 2

예:

var hayStack = new[] {"straw", "needle", "straw", "straw", "needle"};
var nNeedles = hayStack.Aggregate(0, (n, e) => e == "needle" ? n+1 : n);  // 2


이 과부하가 더 일반적입니다.

  • 시드 값을 제공해야합니다 ( bIn).
  • 컬렉션이 비어있을 수 있습니다
    .이 경우 함수는 결과적으로 시드 값을 생성합니다.
  • 요소와 결과는 다른 유형을 가질 수 있습니다.



과부하 3 :

C Aggregate<A,B,C>(IEnumerable<A> a, B bIn, Func<B,A,B> f, Func<B,C> f2)


세 번째 과부하는 그다지 유용한 IMO가 아닙니다.
오버로드 2를 사용하고 결과를 변환하는 함수를 사용하여 더 간결하게 작성할 수 있습니다.


그림은 이 훌륭한 블로그 포스트 에서 수정되었습니다 .


이것은 Haskel에 대한 질문에 대한 훌륭한 답변이 될 것입니다. 그러나 Aggegate.net 에는 과부하가 없습니다 Func<T, T, T>.
Jamiec

4
그렇습니다 . 당신은 당신의 자신의 대답으로 사용합니다!
3dGrabber

1
순서가 비어있을 때 발생하는 일을주의해서 설명하기 때문에 상향 조정 하자 N은 소스의 요소 수합니다. 를 취하지 않는 과부하 seed는 누산기 기능을 N -1 번 적용합니다 . (다른 과부하 상태 않는 걸릴는 seed) 누적 함수를 적용 N 번.
Jeppe Stig Nielsen

17

집계는 기본적으로 데이터를 그룹화하거나 요약하는 데 사용됩니다.

MSDN에 따르면 "집계 함수 시퀀스에 누산기 기능을 적용합니다."

예 1 : 배열의 모든 숫자를 추가하십시오.

int[] numbers = new int[] { 1,2,3,4,5 };
int aggregatedValue = numbers.Aggregate((total, nextValue) => total + nextValue);

* 중요 : 기본적으로 초기 집계 값은 콜렉션 순서에서 1 요소입니다. 즉, 총 변수 초기 값은 기본적으로 1입니다.

변수 설명

total : func이 반환 한 합계 값 (집계 값)을 보유합니다.

nextValue : 배열 순서에서 다음 값입니다. 이 값은 집계 된 값, 즉 총계에 더해지는 것보다 큽니다.

예 2 : 배열의 모든 항목을 추가하십시오. 또한 10부터 시작하여 초기 누산기 값을 설정하십시오.

int[] numbers = new int[] { 1,2,3,4,5 };
int aggregatedValue = numbers.Aggregate(10, (total, nextValue) => total + nextValue);

인수 설명 :

첫 번째 인수는 배열의 다음 값으로 더하기 시작하는 데 사용되는 초기 값 (시작 값, 즉 시드 값)입니다.

두 번째 인수는 2 int를 취하는 func 인 func입니다.

1. 총계 : 계산 후 func에 의해 반환 된 합계 값 (집계 값) 이전과 동일합니다.

2.nextValue : : 배열 순서에서 다음 값입니다. 이 값은 집계 된 값, 즉 총계에 더해지는 것보다 큽니다.

또한이 코드를 디버깅하면 집계가 어떻게 작동하는지 더 잘 이해할 수 있습니다.


7

Jamiec의 답변 에서 많은 것을 배웠습니다 .

CSV 문자열을 생성하는 것만 필요한 경우 시도해 볼 수 있습니다.

var csv3 = string.Join(",",chars);

백만 개의 문자열을 사용한 테스트입니다.

0.28 seconds = Aggregate w/ String Builder 
0.30 seconds = String.Join 

소스 코드는 여기


링크에 제공된 것과 동일한 코드를 dotnetfiddle.net 에서 실행하면 "string.Join"에 대해 "치명적 오류 : 메모리 사용 제한이 초과되었습니다"라는 메시지가 표시되지만 집계는 항상 예상대로 작동했습니다. 내가 믿는 그래서이 String.Join 사용하지 않는 것이 좋습니다
마니 쉬자인

이상한? 내가 집계에 대한 첫 번째 스톱워치를 언급했을 때; "치명적인 오류 : 메모리 사용 한도를 초과했습니다"라는 메시지가 표시되지 않습니다. 설명 해주십시오! 링크 : dotnetfiddle.net/6YyumS
Manish Jain

dotnetfiddle.net에는 실행 중지에 도달 할 때 메모리 제한이 있습니다. String.Join 코드 전에 집계 코드를 이동하면 집계 오류가 발생할 수 있습니다.
Rm558

7

이미 여기에있는 모든 훌륭한 답변 외에도 일련의 변형 단계를 통해 항목을 안내하는 데 사용했습니다.

변환이로 구현 된 경우 Func<T,T>여러 변환을에 추가 하고 각 단계 의 인스턴스를 진행 하는 데 List<Func<T,T>>사용할 수 있습니다 .AggregateT

보다 구체적인 예

당신은 먹고 싶어 string값을, 그리고 프로그래밍 방식으로 구축 할 수있는 텍스트 변환하는 일련의를 통해 도보.

var transformationPipeLine = new List<Func<string, string>>();
transformationPipeLine.Add((input) => input.Trim());
transformationPipeLine.Add((input) => input.Substring(1));
transformationPipeLine.Add((input) => input.Substring(0, input.Length - 1));
transformationPipeLine.Add((input) => input.ToUpper());

var text = "    cat   ";
var output = transformationPipeLine.Aggregate(text, (input, transform)=> transform(input));
Console.WriteLine(output);

이렇게하면 일련의 변형이 생성됩니다. 선행 및 후행 공백 제거-> 첫 문자 제거-> 마지막 문자 제거-> 대문자로 변환 이 체인의 단계는 필요에 따라 추가, 제거 또는 재정렬되어 필요한 모든 종류의 변환 파이프 라인을 생성 할 수 있습니다.

이 특정 파이프 라인의 최종 결과는, 즉 " cat "이된다 "A".


당신 T무엇이든 할 수 있다는 것을 깨닫게되면 이것은 매우 강력해질 수 있습니다 . BitMap예를 들어 필터와 같은 이미지 변환에 사용할 수 있습니다 .


4

정의

집계 방법은 일반 컬렉션의 확장 방법입니다. 집계 방법은 함수를 컬렉션의 각 항목에 적용합니다. 함수를 적용 할뿐만 아니라 결과를 다음 반복의 초기 값으로 사용합니다. 결과적으로 컬렉션에서 계산 된 값 (최소, 최대, 평균 또는 기타 통계 값)을 얻습니다.

따라서 집계 방법은 재귀 함수의 안전한 구현 형식입니다.

재귀는 컬렉션의 각 항목을 반복하고 잘못된 종료 조건으로 인해 무한 루프 일시 중단을 얻을 수 없기 때문에 안전 합니다. 현재 함수의 결과가 다음 함수 호출의 매개 변수로 사용되기 때문에 재귀 .

통사론:

collection.Aggregate(seed, func, resultSelector);
  • seed- 기본적으로 초기 값;
  • func- 재귀 함수. 람다 식, Func 대리자 또는 함수 유형 TF (T result, T nextValue) 일 수 있습니다.
  • resultSelector -func 또는 최종 결과를 계산, 변환, 변경, 변환하는 표현식과 같은 함수일 수 있습니다.

작동 방식 :

var nums = new[]{1, 2};
var result = nums.Aggregate(1, (result, n) => result + n); //result = (1 + 1) + 2 = 4
var result2 = nums.Aggregate(0, (result, n) => result + n, response => (decimal)response/2.0); //result2 = ((0 + 1) + 2)*1.0/2.0 = 3*1.0/2.0 = 3.0/2.0 = 1.5

실제 사용법 :

  1. 숫자 n에서 계승을 구합니다 :

int n = 7;
var numbers = Enumerable.Range(1, n);
var factorial = numbers.Aggregate((result, x) => result * x);

이 기능과 동일한 작업을 수행합니다.

public static int Factorial(int n)
{
   if (n < 1) return 1;

   return n * Factorial(n - 1);
}
  1. Aggregate ()는 Select () 및 Where ()와 같은 가장 강력한 LINQ 확장 방법 중 하나입니다. Sum (), Min ()을 대체하는 데 사용할 수 있습니다. Max (), Avg () 기능 또는 추가 컨텍스트를 구현하여 기능을 변경하려면 다음을 수행하십시오.
    var numbers = new[]{3, 2, 6, 4, 9, 5, 7};
    var avg = numbers.Aggregate(0.0, (result, x) => result + x, response => (double)response/(double)numbers.Count());
    var min = numbers.Aggregate((result, x) => (result < x)? result: x);
  1. 확장 메소드의보다 복잡한 사용법 :
    var path = @“c:\path-to-folder”;

    string[] txtFiles = Directory.GetFiles(path).Where(f => f.EndsWith(“.txt”)).ToArray<string>();
    var output = txtFiles.Select(f => File.ReadAllText(f, Encoding.Default)).Aggregate<string>((result, content) => result + content);

    File.WriteAllText(path + summary.txt”, output, Encoding.Default);

    Console.WriteLine(“Text files merged into: {0}”, output); //or other log info

아주 좋은 첫 번째 대답. 잘 했어! 부끄러운 질문이거나 수치
스러울

1

AggregateLinq Sorting과 같은 Fluent API 사용 에 대한 설명 입니다.

var list = new List<Student>();
var sorted = list
    .OrderBy(s => s.LastName)
    .ThenBy(s => s.FirstName)
    .ThenBy(s => s.Age)
    .ThenBy(s => s.Grading)
    .ThenBy(s => s.TotalCourses);

필드 집합을 취하는 정렬 함수를 구현하고자한다면 Aggregate다음과 같이 for-loop 대신에 사용 하는 것이 매우 쉽습니다 .

public static IOrderedEnumerable<Student> MySort(
    this List<Student> list,
    params Func<Student, object>[] fields)
{
    var firstField = fields.First();
    var otherFields = fields.Skip(1);

    var init = list.OrderBy(firstField);
    return otherFields.Skip(1).Aggregate(init, (resultList, current) => resultList.ThenBy(current));
}

그리고 우리는 이것을 다음과 같이 사용할 수 있습니다 :

var sorted = list.MySort(
    s => s.LastName,
    s => s.FirstName,
    s => s.Age,
    s => s.Grading,
    s => s.TotalCourses);

1

모두가 그의 설명을했습니다. 내 설명은 그와 같습니다.

집계 방법은 함수를 컬렉션의 각 항목에 적용합니다. 예를 들어 {6, 2, 8, 3} 컬렉션과 Add (operator +) 함수를 수행하고 (((6 + 2) +8) +3) 함수를 반환하고 19를 반환합니다

var numbers = new List<int> { 6, 2, 8, 3 };
int sum = numbers.Aggregate(func: (result, item) => result + item);
// sum: (((6+2)+8)+3) = 19

이 예제에서는 람다 식 대신 Add라는 메서드가 전달되었습니다.

var numbers = new List<int> { 6, 2, 8, 3 };
int sum = numbers.Aggregate(func: Add);
// sum: (((6+2)+8)+3) = 19

private static int Add(int x, int y) { return x + y; }

0

Linq Aggregate 확장 방법을 사용하면 목록의 요소에 적용되는 일종의 재귀 함수를 선언 할 수 있습니다. 피연산자는 두 가지입니다. 한 번에 하나의 요소 및 이전 재귀 반복의 결과 또는 아직 재귀하지 않으면 아무것도 없습니다.

이 방법으로 숫자의 계승을 계산하거나 문자열을 연결할 수 있습니다.


0

다차원 정수 배열에서 열을 합산하는 데 사용되는 집계

        int[][] nonMagicSquare =
        {
            new int[] {  3,  1,  7,  8 },
            new int[] {  2,  4, 16,  5 },
            new int[] { 11,  6, 12, 15 },
            new int[] {  9, 13, 10, 14 }
        };

        IEnumerable<int> rowSums = nonMagicSquare
            .Select(row => row.Sum());
        IEnumerable<int> colSums = nonMagicSquare
            .Aggregate(
                (priorSums, currentRow) =>
                    priorSums.Select((priorSum, index) => priorSum + currentRow[index]).ToArray()
                );

선택 기능은 집계 기능 내에서 일치하는 열을 합산하고 새 배열을 반환하는 데 사용됩니다. {3 + 2 = 5, 1 + 4 = 5, 7 + 16 = 23, 8 + 5 = 13}.

        Console.WriteLine("rowSums: " + string.Join(", ", rowSums)); // rowSums: 19, 27, 44, 46
        Console.WriteLine("colSums: " + string.Join(", ", colSums)); // colSums: 25, 24, 45, 42

그러나 Boolean 배열에서 true 수를 계산하는 것은 누적 유형 (int)이 소스 유형 (bool)과 다르기 때문에 더 어렵습니다. 여기서 두 번째 과부하를 사용하려면 시드가 필요합니다.

        bool[][] booleanTable =
        {
            new bool[] { true, true, true, false },
            new bool[] { false, false, false, true },
            new bool[] { true, false, false, true },
            new bool[] { true, true, false, false }
        };

        IEnumerable<int> rowCounts = booleanTable
            .Select(row => row.Select(value => value ? 1 : 0).Sum());
        IEnumerable<int> seed = new int[booleanTable.First().Length];
        IEnumerable<int> colCounts = booleanTable
            .Aggregate(seed,
                (priorSums, currentRow) =>
                    priorSums.Select((priorSum, index) => priorSum + (currentRow[index] ? 1 : 0)).ToArray()
                );

        Console.WriteLine("rowCounts: " + string.Join(", ", rowCounts)); // rowCounts: 3, 1, 2, 2
        Console.WriteLine("colCounts: " + string.Join(", ", colCounts)); // colCounts: 3, 2, 1, 2
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.