LINQ Toplam algoritması açıklandı


723

Bu topallık gibi gelebilir, ama gerçekten iyi bir açıklama bulamadım Aggregate.

İyi, küçük ve açık bir örnekle kısa, açıklayıcı, kapsamlı anlamına gelir.

Yanıtlar:


1016

Anlaşılması en kolay tanımı Aggregate, listenin her bir elemanı üzerinde, daha önce yapılmış olan işlemleri dikkate alarak bir işlem gerçekleştirmesidir. Yani, birinci ve ikinci eleman üzerindeki eylemi gerçekleştirir ve sonucu ileri taşır. Sonra önceki sonuç ve üçüncü eleman üzerinde çalışır ve ileriye doğru devam eder. vb.

Örnek 1. Sayıları toplama

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

Bu ekler 1ve 2yapmak 3. Sonra yapmak için 3(önceki sonucun sonucu) ve 3(sırayla bir sonraki eleman ) ekler 6. Sonra ekler 6ve 4yapmak 10.

Örnek 2. bir dizeden csv oluşturma

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

Bu aynı şekilde çalışır. Concatenate avirgül ve byapmak a,b. Sonra a,b bir virgül ve cyapmak için bitiştirir a,b,c. ve bunun gibi.

Örnek 3. Bir tohum kullanarak sayıları çarpma

Bütünlüğü sağlamak için, bir olduğu aşırı bir Aggregatetohum değeri alır.

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)

Yukarıdaki örneklere çok benzer şekilde, bu bir değeri ile başlar 5ve 10sonucu veren sekansın ilk elemanı ile çarpar 50. Bu sonuç ileriye taşınır ve 20bir sonuç vermek için dizideki bir sonraki sayıyla çarpılır 1000. Bu, dizinin geri kalan 2 elemanı boyunca devam eder.

Canlı örnekler: http://rextester.com/ZXZ64749
Dokümanlar: http://msdn.microsoft.com/en-us/library/bb548651.aspx


ek

Yukarıdaki örnek 2, virgülle ayrılmış değerlerin bir listesini oluşturmak için dize birleştirmeyi kullanır. Bu, Aggregatebu cevabın amacı olan kullanımı açıklamanın basit bir yoludur . Bununla birlikte, bu tekniği gerçekten büyük miktarda virgülle ayrılmış veri oluşturmak için kullanırsanız, a'nın kullanılması daha uygun olur StringBuilderve bu, Aggregatebaşlatmak için tohumlanmış aşırı yükün kullanılmasıyla tamamen uyumludur StringBuilder.

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);

Güncelleme örneği: http://rextester.com/YZCVXV6464


11
İlk açıklama için başka bir açıklama, sağladığınız işlevin, dizi bir öğeye daraltılana kadar her zaman ilk iki üyeyi birleştirmesidir. O zaman ve sonunda [1,2,3,4]olacak . Ancak tek bir değerin bir dizisini döndürmek yerine, değerin kendisini alırsınız. [3,3,4][6,4][10]
David Raab

2
Bir Toplama işlevinden erken kopabilir / çıkabilir miyim? Örneğin, chars.Aggregate ((a, b) => {if (a == 'a') tüm toplamı kırsa başka bir + +, '+ b} döndürür)
Jeff Tian

13
@JeffTian - Numaralanabilir uzantıların en iyi hali olan TakeWhilebir zincir oluşturmayı öneririm Aggregate- kolayca zincirlenebilirler. Yani sonunda TakeWhile(a => a == 'a').Aggregate(....). Bu örneğe bakın: rextester.com/WPRA60543
Jamiec

2
Zeyilname üzerinde bir sidenote olarak, tüm blok kolayca değiştirilebilir var csv = string.Join(",", chars)(agrega veya dize oluşturucuya gerek yok) - ama evet, cevabın amacının agrega örnek kullanımı vermek olduğunu biliyorum, bu yüzden havalı. Ama yine de sadece dizelere katılmak için tavsiye edilmediğini belirtmek istedim, zaten bunun için adanmış bir yöntem var ....
T_D

2
başka bir yaygın kullanım (şimdiye kadar üretim kodunda gördüğüm tek şey gibi) gibi min veya max öğeleri elde etmektirvar biggestAccount = Accounts.Aggregate((a1, a2) => a1.Amount >= a2.Amount ? a1 : a2);
Franck

133

Kısmen hangi aşırı yükten bahsettiğinize bağlıdır, ancak temel fikir şudur:

  • "Geçerli değer" olarak bir tohumla başlayın
  • Dizi üzerinde tekrarlayın. Sekanstaki her değer için:
    • Dönüştürmek için kullanıcı tanımlı bir işlev (currentValue, sequenceValue)uygulama(nextValue)
    • Ayarlamak currentValue = nextValue
  • Finali iade et currentValue

Yazıyı Edulinq serimde bulabilirsinizAggregate yararlı - bir daha ayrıntılı (çeşitli aşırı dahil) açıklamasına ve uygulamaları içermektedir.

Basit bir örnek aşağıdakilere Aggregatealternatif olarak kullanmaktır 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);

Veya belki de dizelerin tüm uzunluklarını bir dizi dizede toplamak:

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

Şahsen nadirenAggregate yararlı buluyorum - "özel" toplama yöntemleri genellikle benim için yeterince iyi.


6
@Jon Çalışmanın çekirdekler arasında bölünebilmesi için öğeleri bir ağaca ayıran Asgaride asenkron varyasyonları var mı? Yöntemin tasarımı "azaltma" veya "katlama" kavramlarıyla tutarlı görünüyor, ancak bunu gerçekten başlık altında mı, yoksa sadece öğeler listesi üzerinden mi yinelediğini bilmiyorum.
AaronLS

@Jon: yukarıda belirtilen edulink çalışmıyor beni doğru bağlantıya yönlendirebilir misin. Ve cevabınızda kullandığınız "uyarlanmış" toplama işlevleri terimiyle ilgili daha ayrıntılı bilgi verebilir misiniz?
Koushik

1
@Koushik: Yazıdaki bağlantıyı düzelttim. "Özelleştirilmiş" toplama işlevleri ile Max / Min / Count / Sum gibi şeyleri kastediyorum.
Jon Skeet

62

Süper kısa Agrega Haskell / ML / F # 'da kat gibi çalışır.

Biraz daha uzun . .Aggregate (), geliştiricinin başlangıç ​​durumunu (aka tohum olarak) ve toplama işlevini belirtmesine izin verdiği için genelleştirilmiş bir toplayıcıdır.

Kısa bir açıklama istediğini biliyorum ama başkalarının birkaç kısa cevap verdiğini düşündüm, belki biraz daha uzun biriyle ilgileneceğini düşündüm

Kodlu uzun versiyon Neyin ne olduğunu göstermenin bir yolu, bir kez foreach ve bir kez .Aggregate kullanarak örnek standart sapmayı nasıl uyguladığınızı gösterebilir. Not: Burada performansa öncelik vermedim, bu yüzden gereksiz yere koleksiyon üzerinde birkaç kez tekrar ediyorum

İlk olarak, ikinci dereceden mesafelerin toplamını oluşturmak için kullanılan bir yardımcı işlev:

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

Sonra ForEach kullanarak Örnek Standart Sapma:

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));
}

Sonra bir kez kullanarak.

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));
}

Bu işlevlerin sumOfQuadraticDistance'ın nasıl hesaplandığı dışında özdeş olduğunu unutmayın:

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

Karşı:

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

Yani .Aggregate'in yaptığı, bu toplayıcı modelini kapsadığı ve .Aggregate'in uygulanmasının şöyle görüneceğini umuyorum:

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;
}

Standart sapma işlevlerini kullanmak şöyle görünecektir:

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);

Benim nacizane fikrime göre

.Aggregate okunabilirliğe yardımcı oluyor mu? Genel olarak LINQ'yu seviyorum çünkü düşünüyorum. Agrega bütünlük nedenlerinden ötürü Linq'te olmak zorundadır, ancak şahsen o kadar ikna olmadım.


+1 Mükemmel! Ancak uzantı yöntemleri SampleStandardDeviation_Aggregate()ve SampleStandardDeviation_ForEach()olamaz private(varsayılan olarak bir erişim niteleyicisi yokluğunda), bu yüzden ya tahakkuk ettirilmiş olmalıydı publicveya internalbana öyle görünüyor
Fulproof

FYI: Eğer doğru hatırlıyorum eğer benim örnekte uzantısı yöntemleri onları kullanan aynı sınıfın bir parçası olduğunu ==> bu durumda özel çalışır.
Başka bir metaprogramcı

39

Bir resim bin kelime değerinde bir olup

Hatırlatma:
Func<X, Y, R>iki tip giriş XveY tip bir sonuç verir olduğunu, R.

Agrega'da üç aşırı yükleme var:


Aşırı yük 1:

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

Aggregate1

Misal:

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


Bu aşırı yükleme basittir, ancak aşağıdaki sınırlamalara sahiptir:

  • sekans en az bir eleman içermelidir,
    aksi takdirde işlev bir atar InvalidOperationException.
  • elemanlar ve sonuç aynı tipte olmalıdır.



Aşırı yük 2:

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

Aggregate2

Misal:

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


Bu aşırı yüklenme daha geneldir:

  • bir tohum değeri sağlanmalıdır ( bIn).
  • toplama boş olabilir,
    bu durumda fonksiyon sonuç olarak tohum değerini verecektir.
  • elemanlar ve sonuç farklı tiplerde olabilir.



Aşırı yük 3:

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


Üçüncü aşırı yük çok yararlı IMO değildir.
Aynı şey, aşırı yüklenme 2 ve ardından sonucunu dönüştüren bir fonksiyon kullanılarak daha kısa sürede yazılabilir.


Resimler bu mükemmel blog yazısından uyarlanmıştır .


Bu Haskel hakkında bir soru .... için harika bir cevap olurdu. Ama Aggegate.net içinde aşırı yük yoktur Func<T, T, T>.
Temmuz

4
Evet var . Kendi cevabınızda kullanıyorsunuz!
3dGrabber

1
Yukarı oylama, çünkü dizi boş olduğunda ne olduğunu dikkatlice açıklarsınız. N , kaynaktaki öğelerin sayısı olsun . A almayan aşırı yükün seed, akümülatör fonksiyonunu N -1 kez uyguladığını gözlemliyoruz ; (diğer aşırı yükler iken do almak bir seed) akümülatör fonksiyonunu uygulamak N kez.
Jeppe Stig Nielsen

17

Agrega temel olarak verileri Gruplamak veya Özetlemek için kullanılır.

MSDN'ye göre "Toplama İşlevi Bir dizi üzerine bir akümülatör işlevi uygular."

Örnek 1: Bir dizideki tüm sayıları ekleyin.

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

* important: Varsayılan olarak ilk toplam değer, toplama sırasındaki 1 öğedir. ie: toplam değişken başlangıç ​​değeri varsayılan olarak 1 olacaktır.

değişken açıklama

total: işlev tarafından döndürülen toplam değeri (toplanmış değer) tutacaktır.

nextValue: dizi dizisindeki sonraki değerdir. Bu değer, toplam değere, yani toplam değerine eklenir.

Örnek 2: Bir dizideki tüm öğeleri ekleyin. Ayrıca 10 ile eklemeye başlamak için ilk akümülatör değerini ayarlayın.

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

argüman açıklaması:

ilk argüman, dizideki bir sonraki değerle toplamaya başlamak için kullanılacak başlangıç ​​değeridir (başlangıç ​​değeri, yani tohum değeri).

ikinci argüman 2 int alan bir fonktur.

1. toplam: bu, hesaplamadan sonra işlev tarafından döndürülen toplama değerinden (toplanan değer) önceki ile aynı olacaktır.

2.nextValue:: dizi dizisindeki sonraki değerdir. Bu değer, toplam değere, yani toplam değerine eklenir.

Ayrıca bu kodda hata ayıklamak, toplamın nasıl çalıştığını daha iyi anlamanıza yardımcı olur.


7

Jamiec'den çok şey öğrendim .

Tek ihtiyaç CSV dizesi oluşturmaksa, bunu deneyebilirsiniz.

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

İşte 1 milyon dizeyle bir test

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

Kaynak kodu burada


Bağlantıda sağlanan dotnetfiddle.net aynı kodu çalıştırdığımda, "String.Join" için "Önemli Hata: Bellek kullanım sınırı aşıldı" var ama Aggregate her zaman beklendiği gibi çalıştı. Bu yüzden bunun String.Join kullanmanın tavsiye edilmediğine inanıyorum
Manish Jain

Garip? Ben Aggregate için olan ilk stop watch yorum yaparken; "Önemli Hata: Bellek kullanım limiti aşıldı" almıyorum. Lütfen açıkla! Bağlantı: dotnetfiddle.net/6YyumS
Manish Jain

dotnetfiddle.net, yürütme durağına ulaşırken bir bellek sınırına sahiptir. toplu kodu String.Join kodundan önce taşırsanız, toplama için hata alabilirsiniz.
Rm558

7

Buradaki tüm harika cevaplara ek olarak, bir dizi dönüşüm adımında bir öğeyi yürümek için de kullandım.

Bir dönüşüm a olarak uygulanırsa, a Func<T,T>öğesine birkaç dönüşüm ekleyebilir List<Func<T,T>>ve her adımda Aggregatebir örneğini yürütmek için kullanabilirsiniz T.

Daha somut bir örnek

Bir stringdeğer almak ve bunu programlı olarak oluşturulabilecek bir dizi metin dönüşümünden geçmek istiyorsunuz .

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);

Bu bir dönüşüm zinciri oluşturacaktır: Baştaki ve sondaki boşlukları kaldırın -> ilk karakteri kaldır -> son karakteri kaldır -> büyük harfe dönüştür. Gerekli her türlü dönüşüm boru hattını oluşturmak için bu zincirdeki adımlar gerektiğinde eklenebilir, çıkarılabilir veya yeniden sıralanabilir.

Bu spesifik boru hattının nihai sonucu, " cat "olur "A".


Bunun herhangi bir şeyT olabileceğini anladıktan sonra bu çok güçlü olabilir . Bu, örnek olarak , filtreler gibi görüntü dönüşümleri için kullanılabilir ;BitMap


4

Tanım

Toplama yöntemi, genel koleksiyonlar için bir genişletme yöntemidir. Toplama yöntemi, koleksiyonun her öğesine bir işlev uygular. Sadece bir işlev uygulamakla kalmaz, sonucunu bir sonraki yineleme için başlangıç ​​değeri olarak alır. Sonuç olarak, bir koleksiyondan hesaplanmış bir değer (min, maks, ort veya başka bir istatistiksel değer) alırız.

Bu nedenle, Toplam yöntemi, özyinelemeli bir işlevin güvenli bir şekilde uygulanmasıdır.

Güvenli , çünkü özyineleme bir koleksiyonun her öğesi üzerinde yinelenir ve yanlış çıkış koşulu ile sonsuz döngü süspansiyonu alamazız. Özyinelemeli , çünkü geçerli işlevin sonucu bir sonraki işlev çağrısı için parametre olarak kullanılır.

Sözdizimi:

collection.Aggregate(seed, func, resultSelector);
  • tohum - varsayılan olarak başlangıç ​​değeri;
  • fonk - özyinelemeli işlevimiz. Bir lambda ifadesi, bir Func delegesi veya bir işlev türü TF (T sonucu, T nextValue) olabilir;
  • sonuçSeçici - func gibi bir işlev veya nihai sonucu hesaplamak, dönüştürmek, değiştirmek, dönüştürmek için bir ifade olabilir.

Nasıl çalışır:

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

Pratik kullanım:

  1. N numarasından Faktöriyeli Bul:

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

Bu işlevle aynı şeyi yapıyor:

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

   return n * Factorial(n - 1);
}
  1. Aggregate (), Select () ve Where () gibi en güçlü LINQ uzantı yöntemlerinden biridir. Sum (), Min () yerine koymak için kullanabiliriz. Maks (), Avg () işlevselliği veya ek bağlam uygulayarak değiştirmek için:
    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. Genişletme yöntemlerinin daha karmaşık kullanımı:
    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

İlk cevap çok iyi. Aferin! Utanç bu kadar eski bir soru ya da çok sayıda oyunuz olurdu
Jamiec

1

Bu, AggregateLinq Sorting gibi bir Akıcı API üzerinde kullanımla ilgili bir açıklamadır .

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);

ve bir dizi alanı alan bir sıralama işlevi uygulamak istediğimizi görelim, Aggregatefor-loop yerine şu şekilde kullanımı çok kolaydır :

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));
}

Ve bunu şu şekilde kullanabiliriz:

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

1

Herkes açıklamasını yaptı. Benim açıklamam böyle.

Toplama yöntemi, koleksiyonun her öğesine bir işlev uygular. Örneğin, {6, 2, 8, 3} koleksiyonuna ve sahip olduğu Ekle (işleç +) işlevine sahip olalım (((6 + 2) +8) +3) ve 19 döndürür

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

Bu örnekte lambda ifadesi yerine Add adlı yöntem kullanılmıştır.

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

Kısa ve temel bir tanım şu olabilir: Linq Agrega genişletme yöntemi, bir işlenenin iki olduğu bir listenin öğelerine uygulanan bir tür özyinelemeli işlev bildirmeye izin verir: Listede bulundukları sırayla öğeler, bir kerede bir öğe ve önceki özyinelemeli yinelemenin sonucu veya henüz özyineleme değilse hiçbir şey.

Bu şekilde sayıların faktöriyelini hesaplayabilir veya dizeleri birleştirebilirsiniz.


0

Çok boyutlu bir tamsayı dizisindeki sütunları toplamak için kullanılan toplama

        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()
                );

Dizini ile seç, Toplama işlevi içinde eşleşen sütunları toplamak ve yeni bir Dizi döndürmek için kullanılır; {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

Ancak, bir Boolean dizisindeki trues sayısını saymak daha zordur çünkü biriken tip (int) kaynak tipinden (bool) farklıdır; burada ikinci aşırı yükü kullanmak için bir tohum gereklidir.

        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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.