Algoritma Agregat LINQ menjelaskan

722

Ini mungkin terdengar lemah, tetapi saya belum dapat menemukan penjelasan yang sangat bagus Aggregate.

Baik berarti pendek, deskriptif, komprehensif dengan contoh kecil dan jelas.

Alexander Beletsky
sumber

Jawaban:

1015

Definisi yang paling mudah dipahami Aggregateadalah melakukan operasi pada setiap elemen daftar dengan mempertimbangkan operasi yang telah berjalan sebelumnya. Maksudnya melakukan aksi pada elemen pertama dan kedua dan membawa hasilnya ke depan. Kemudian beroperasi pada hasil sebelumnya dan elemen ketiga dan berjalan maju. dll.

Contoh 1. Menjumlahkan angka

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

Ini menambah 1dan 2membuat 3. Kemudian tambahkan 3(hasil sebelumnya) dan 3(elemen berikutnya secara berurutan) untuk dibuat 6. Kemudian tambahkan 6dan 4buat 10.

Contoh 2. buat csv dari array string

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

Ini bekerja dengan cara yang hampir sama. Menggabungkan akoma dan buntuk membuat a,b. Kemudian digabungkan a,b dengan koma dan cuntuk membuatnya a,b,c. dan seterusnya.

Contoh 3. Mengalikan angka menggunakan seed

Untuk kelengkapan, ada kelebihan dari Aggregateyang membutuhkan nilai benih.

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)

Sama seperti contoh di atas, ini dimulai dengan nilai 5dan mengalikannya dengan elemen pertama dari urutan 10memberikan hasil 50. Hasil ini diteruskan dan dikalikan dengan angka berikutnya dalam urutan 20untuk memberikan hasil 1000. Ini berlanjut melalui sisa 2 elemen dari urutan.

Contoh langsung: http://rextester.com/ZXZ64749
Documents: http://msdn.microsoft.com/en-us/library/bb548651.aspx


Tambahan

Contoh 2, di atas, menggunakan penggabungan string untuk membuat daftar nilai yang dipisahkan oleh koma. Ini adalah cara sederhana untuk menjelaskan penggunaan Aggregateyang merupakan maksud dari jawaban ini. Namun, jika menggunakan teknik ini untuk benar-benar membuat sejumlah besar data yang dipisahkan koma, akan lebih tepat untuk menggunakan StringBuilder, dan ini sepenuhnya kompatibel dengan Aggregatemenggunakan seeded overload untuk memulai 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);

Contoh yang diperbarui: http://rextester.com/YZCVXV6464

Jamiec
sumber
11
Penjelasan lain untuk deskripsi pertama adalah bahwa fungsi yang Anda berikan selalu menggabungkan dua anggota pertama hingga array menyusut menjadi satu elemen. Begitu [1,2,3,4]juga [3,3,4]saat itu [6,4]dan akhirnya [10]. Tetapi alih-alih mengembalikan array nilai tunggal Anda hanya mendapatkan nilai itu sendiri.
David Raab
2
Bisakah saya memulai / keluar lebih awal dari fungsi Agregat? Misalnya, chars.Aggregate ((a, b) => {if (a == 'a') hancurkan seluruh agregat yang lain mengembalikan a + ',' + b})
Jeff Tian
13
@JeffTian - Saya akan menyarankan chaining TakeWhilesebuah Aggregate- thats beatuty dari ekstensi Enumerable - mudah dirantai. Jadi Anda berakhir dengan TakeWhile(a => a == 'a').Aggregate(....). Lihat contoh ini: rextester.com/WPRA60543
Jamiec
2
Sebagai sidenote pada addendum, seluruh blok dapat dengan mudah diganti oleh var csv = string.Join(",", chars)(tidak perlu agregat atau pembuat string) - tapi ya, saya tahu bahwa jawabannya adalah untuk memberikan contoh penggunaan agregat sehingga keren. Tapi saya masih ingin menyebutkan bahwa itu tidak disarankan untuk hanya bergabung dengan string, sudah ada metode yang didedikasikan untuk itu ....
T_D
2
penggunaan umum lainnya (sejauh ini satu-satunya yang saya lihat dalam kode produksi) adalah untuk mendapatkan barang-barang min atau max sepertivar biggestAccount = Accounts.Aggregate((a1, a2) => a1.Amount >= a2.Amount ? a1 : a2);
Franck
133

Sebagian tergantung pada kelebihan beban yang Anda bicarakan, tetapi ide dasarnya adalah:

  • Mulai dengan seed sebagai "nilai saat ini"
  • Ulangi urutannya. Untuk setiap nilai dalam urutan:
    • Terapkan fungsi yang ditentukan pengguna untuk diubah (currentValue, sequenceValue)menjadi(nextValue)
    • Set currentValue = nextValue
  • Kembalikan final currentValue

Anda mungkin menemukan Aggregateposting dalam seri Edulinq saya bermanfaat - termasuk deskripsi yang lebih rinci (termasuk berbagai kelebihan) dan implementasi.

Salah satu contoh sederhana menggunakan Aggregatesebagai alternatif untuk 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);

Atau mungkin menjumlahkan semua panjang string dalam urutan string:

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

Secara pribadi saya jarang menemukan Aggregateberguna - metode agregasi "disesuaikan" biasanya cukup baik untuk saya.

Jon Skeet
sumber
6
@ Jon Apakah ada variasi Agregat asinkron yang membagi item menjadi pohon sehingga pekerjaan dapat dibagi antara inti? Sepertinya desain metode ini konsisten dengan konsep "mengurangi" atau "melipat", tetapi saya tidak tahu apakah itu benar-benar melakukan itu di bawah tenda, atau hanya mengulangi daftar item.
AaronLS
@ Jon: edulink yang disebutkan di atas tidak berfungsi, bisakah Anda mengarahkan saya ke tautan yang benar. Dan bisakah Anda lebih spesifik tentang fungsi agregasi istilah "khusus" yang Anda gunakan dalam jawaban Anda.
Koushik
1
@ Koushik: Saya telah memperbaiki tautan di pos. Dengan fungsi agregasi "khusus" yang saya maksud hal-hal seperti Max / Min / Count / Sum.
Jon Skeet
62

Agregat super pendek berfungsi seperti lipatan di Haskell / ML / F #.

Sedikit lebih lama .Max (), .Min (), .Sum (), .Rata-rata () semuanya mengulangi elemen-elemen secara berurutan dan menggabungkannya menggunakan fungsi agregat masing-masing. .Aggregate () adalah agregator yang digeneralisasi karena memungkinkan pengembang untuk menentukan status awal (alias seed) dan fungsi agregat.

Saya tahu Anda meminta penjelasan singkat tetapi saya pikir ketika orang lain memberikan beberapa jawaban singkat saya pikir Anda mungkin akan tertarik pada yang sedikit lebih lama

Versi panjang dengan kode Salah satu cara untuk menggambarkan apa fungsinya adalah menunjukkan bagaimana Anda menerapkan Contoh Standar Deviasi sekali menggunakan foreach dan sekali menggunakan .Aggregate. Catatan: Saya belum memprioritaskan kinerja di sini jadi saya harus mengulangi beberapa kali selama tidak perlu colleciton

Pertama, fungsi pembantu yang digunakan untuk membuat jumlah jarak kuadratik:

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

Kemudian Contoh Deviasi Standar menggunakan 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));
}

Kemudian sekali menggunakan .Aregregate:

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

Perhatikan bahwa fungsi-fungsi ini identik kecuali untuk bagaimana sumOfQuadraticDistance dihitung:

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

Melawan:

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

Jadi apa yang dilakukan .Aregregate adalah bahwa ia merangkum pola agregator ini dan saya berharap bahwa implementasi .Aggregate akan terlihat seperti ini:

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

Menggunakan fungsi standar deviasi akan terlihat seperti ini:

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

Menurut opini saya

Jadi, apakah .Aregregate membantu keterbacaan? Secara umum saya suka LINQ karena saya pikir. Dimana, .Pilih, .OrderBy dan seterusnya sangat membantu keterbacaan (jika Anda menghindari hirarki inline. Pilih). Agregat harus ada di Linq untuk alasan kelengkapan tetapi secara pribadi saya tidak begitu yakin bahwa. Agregat menambah keterbacaan dibandingkan dengan foreach yang ditulis dengan baik.

Hanya pembuat program lain
sumber
+1 Luar Biasa! Tetapi metode ekstensi SampleStandardDeviation_Aggregate()dan SampleStandardDeviation_ForEach()tidak dapat private(secara default tidak adanya kualifikasi akses), jadi seharusnya telah publicinternal
diakuisisi
FYI: Jika saya ingat dengan benar metode ekstensi dalam sampel saya adalah bagian dari kelas yang sama yang menggunakannya ==> karya pribadi dalam kasus ini.
Hanya pembuat program lain
39

Sebuah gambar bernilai ribuan kata

Pengingat:
Func<X, Y, R>adalah fungsi dengan dua input tipe Xdan Y, yang mengembalikan hasil tipe R.

Enumerable.Aggregate memiliki tiga kelebihan:


Kelebihan 1:

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

Agregat1

Contoh:

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


Kelebihan ini sederhana, tetapi memiliki batasan berikut:

  • urutan harus mengandung setidaknya satu elemen,
    jika tidak fungsi akan melempar InvalidOperationException.
  • elemen dan hasil harus dari jenis yang sama.



Kelebihan 2:

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

Agregat2

Contoh:

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


Kelebihan ini lebih umum:

  • nilai benih harus disediakan ( bIn).
  • koleksi dapat kosong,
    dalam hal ini, fungsi akan menghasilkan nilai seed sebagai hasilnya.
  • elemen dan hasil dapat memiliki berbagai jenis.



Kelebihan 3:

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


Kelebihan ketiga adalah IMO yang tidak terlalu berguna.
Hal yang sama dapat ditulis lebih ringkas dengan menggunakan overload 2 diikuti oleh fungsi yang mengubah hasilnya.


Ilustrasi diadaptasi dari blogpost yang luar biasa ini .

3dGrabber
sumber
Ini akan menjadi jawaban yang bagus .... pada pertanyaan tentang Haskel. Tetapi tidak ada kelebihan Aggegatedalam. Net yang membutuhkan Func<T, T, T>.
Jamiec
4
Ya ada . Anda menggunakannya dalam jawaban Anda sendiri!
3dGrabber
1
Upvoting karena Anda dengan cermat menggambarkan apa yang terjadi ketika urutannya kosong. Misalkan N adalah jumlah elemen dalam sumber. Kami mengamati bahwa kelebihan yang tidak mengambil seed, berlaku fungsi akumulator N -1 kali; sedangkan overloads lain (yang tidak mengambil seed) menerapkan fungsi akumulator N kali.
Jeppe Stig Nielsen
17

Agregat pada dasarnya digunakan untuk mengelompokkan atau menjumlahkan data.

Menurut MSDN "Fungsi Agregat Menerapkan fungsi akumulator pada suatu urutan."

Contoh 1: Tambahkan semua angka dalam array.

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

* Penting: Nilai agregat awal secara default adalah elemen 1 dalam urutan koleksi. yaitu: nilai total variabel awal akan menjadi 1 secara default.

penjelasan variabel

total: itu akan menyimpan nilai penjumlahan (nilai agregat) yang dikembalikan oleh func.

nextValue: ini adalah nilai berikutnya dalam urutan array. Nilai ini kemudian ditambahkan ke nilai agregat yaitu total.

Contoh 2: Tambahkan semua item dalam array. Juga atur nilai akumulator awal untuk mulai menambahkan dengan dari 10.

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

penjelasan argumen:

argumen pertama adalah nilai awal (nilai awal yaitu nilai awal) yang akan digunakan untuk memulai penambahan dengan nilai berikutnya dalam array.

argumen kedua adalah fungsi yang merupakan fungsi yang membutuhkan 2 int.

1.total: ini akan tetap sama seperti sebelum nilai penjumlahan (nilai agregat) dikembalikan oleh func setelah perhitungan.

2.nextValue:: ini adalah nilai berikutnya dalam urutan array. Nilai ini kemudian ditambahkan ke nilai agregat yaitu total.

Juga debug kode ini akan memberi Anda pemahaman yang lebih baik tentang cara kerja agregat.

maxspan
sumber
7

Belajar banyak dari jawaban Jamiec .

Jika satu-satunya kebutuhan adalah untuk menghasilkan string CSV, Anda dapat mencoba ini.

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

Ini adalah tes dengan 1 juta string

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

Kode sumber ada di sini

Rm558
sumber
Ketika saya menjalankan kode yang sama di dotnetfiddle.net seperti yang disediakan di tautan, saya mendapat "Kesalahan Fatal: Batas penggunaan memori terlampaui" untuk "string.Join" tetapi Agregat selalu berfungsi seperti yang diharapkan. Jadi saya percaya ini tidak dianjurkan untuk menggunakan String.Join
Manish Jain
Aneh? Ketika saya berkomentar First stop watch yang untuk Agregat; maka saya tidak mendapatkan "Kesalahan Fatal: Batas penggunaan memori terlampaui". Tolong jelaskan! Tautan: dotnetfiddle.net/6YyumS
Manish Jain
dotnetfiddle.net memiliki batas memori, ketika mencapai eksekusi berhenti. jika Anda memindahkan kode agregat sebelum kode String.Join, Anda mungkin mendapatkan kesalahan untuk agregat.
Rm558
7

Selain semua jawaban hebat di sini, saya juga menggunakannya untuk memandu item melalui serangkaian langkah transformasi.

Jika transformasi diimplementasikan sebagai a Func<T,T>, Anda dapat menambahkan beberapa transformasi ke a List<Func<T,T>>dan gunakan Aggregateuntuk menjalankan instance dari Tsetiap langkah.

Contoh yang lebih konkret

Anda ingin mengambil stringnilai, dan berjalan melalui serangkaian transformasi teks yang bisa dibangun secara programatik.

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

Ini akan membuat rantai transformasi: Hapus spasi awal dan akhir -> hapus karakter pertama -> hapus karakter terakhir -> konversi ke huruf besar. Langkah-langkah dalam rantai ini dapat ditambahkan, dihapus, atau disusun ulang sesuai kebutuhan, untuk membuat jenis pipa transformasi apa pun yang diperlukan.

Hasil akhir dari pipa khusus ini, adalah " cat "menjadi "A".


Ini bisa menjadi sangat kuat begitu Anda menyadari bahwa itu Tbisa menjadi apa saja . Ini dapat digunakan untuk transformasi gambar, seperti filter, menggunakan BitMapsebagai contoh;

Bradley Uffner
sumber
4

Definisi

Metode agregat adalah metode ekstensi untuk koleksi umum. Metode agregat berlaku fungsi untuk setiap item koleksi. Tidak hanya hanya menerapkan fungsi, tetapi mengambil hasilnya sebagai nilai awal untuk iterasi berikutnya. Jadi, sebagai hasilnya, kami akan mendapatkan nilai yang dihitung (min, maks, rata-rata, atau nilai statistik lainnya) dari koleksi.

Oleh karena itu, metode agregat adalah bentuk implementasi yang aman dari fungsi rekursif.

Aman , karena rekursi akan beralih ke setiap item koleksi dan kami tidak bisa mendapatkan suspensi loop tak terbatas dengan kondisi keluar yang salah. Rekursif , karena hasil fungsi saat ini digunakan sebagai parameter untuk panggilan fungsi berikutnya.

Sintaksis:

collection.Aggregate(seed, func, resultSelector);
  • seed - nilai awal secara default;
  • func - fungsi rekursif kami. Ini bisa berupa ekspresi lambda, delegasi Func atau tipe fungsi TF (hasil T, T nextValue);
  • resultSelector - dapat berupa fungsi seperti func atau ekspresi untuk menghitung, mengubah, mengubah, mengonversi hasil akhir.

Bagaimana itu bekerja:

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

Penggunaan praktis:

  1. Cari faktorial dari angka n:

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

yang melakukan hal yang sama dengan fungsi ini:

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

   return n * Factorial(n - 1);
}
  1. Aggregate () adalah salah satu metode ekstensi LINQ yang paling kuat, seperti Select () dan Where (). Kita bisa menggunakannya untuk mengganti Sum (), Min (). Fungsionalitas Max (), Avg (), atau untuk mengubahnya dengan menerapkan konteks tambahan:
    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. Penggunaan metode ekstensi yang lebih kompleks:
    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
YuriUn
sumber
Jawaban pertama yang cukup bagus. Sudah selesai dilakukan dengan baik! Malu itu pertanyaan yang sangat lama atau Anda akan mendapatkan banyak
dukungan
1

Ini adalah penjelasan tentang penggunaan Aggregatepada API Lancar seperti Sortasi Linq.

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

dan mari kita lihat kita ingin mengimplementasikan fungsi sortir yang mengambil seperangkat bidang, ini sangat mudah digunakan Aggregatedaripada for-loop, seperti ini:

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

Dan kita bisa menggunakannya seperti ini:

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

Setiap orang telah memberikan penjelasannya. Penjelasan saya seperti itu.

Metode agregat berlaku fungsi untuk setiap item koleksi. Misalnya, mari kita koleksi {6, 2, 8, 3} dan fungsi Tambahkan (operator +) tidak (((6 + 2) +8) +3) dan mengembalikan 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

Dalam contoh ini ada yang lulus bernama metode Tambahkan bukan ekspresi lambda.

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; }
bizimunda
sumber
0

Definisi pendek dan esensial mungkin adalah ini: Metode ekstensi Agregat Linq memungkinkan untuk mendeklarasikan semacam fungsi rekursif yang diterapkan pada elemen daftar, operan di antaranya adalah dua: elemen dalam urutan di mana mereka hadir dalam daftar, satu elemen pada satu waktu, dan hasil dari iterasi rekursif sebelumnya atau tidak sama sekali jika belum rekursi.

Dengan cara ini Anda dapat menghitung faktorial angka, atau string gabungan.

Ciro Corvino
sumber
0

Agregat digunakan untuk menjumlahkan kolom dalam array integer multi dimensi

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

Pilih dengan indeks digunakan dalam fungsi Agregat untuk menjumlahkan kolom yang cocok dan mengembalikan Array baru; {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

Tetapi menghitung jumlah true dalam array Boolean lebih sulit karena tipe akumulasi (int) berbeda dari tipe sumber (bool); di sini benih diperlukan untuk menggunakan kelebihan kedua.

        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
Dan M.
sumber