Fold and Reduce in LINQ
- 2 minutes read - 301 wordsIn functional programming languages, there are several difference betwee them. I was quite interested in functional programming, even I spent some time to learn haskel and scala. I knew what I can use Select
for map
, not sure about folder
and reduce
Feature | Fold | Reduce |
---|---|---|
Initial Value | Requires an initial value. | Does not require an initial value. |
Function Signature | (A, B) => A | (A, A) => A |
Applicability | Can be used on empty collections. | Requires a non-empty collection. |
Variants | foldLeft and foldRight | reduceLeft and reduceRight |
Starting Point | foldLeft starts from the left. | reduceLeft starts from the left. |
foldRight starts from the right. | reduceRight starts from the right. | |
Common Use Cases | Aggregations with a need for an initial value (e.g., summation, product, etc.). | Aggregations where the collection is guaranteed to be non-empty and no initial value is needed. |
Example Syntax | foldLeft(initialValue)(operation) | reduceLeft(operation) |
foldRight(initialValue)(operation) | reduceRight(operation) | |
Example | List(1, 2, 3).foldLeft(0)(_ + _) | List(1, 2, 3).reduceLeft(_ + _) |
Flexibility | More flexible; can transform types (e.g., from list of integers to a string). | Less flexible; typically reduces to the same type as the elements. |
Handling Empty Collections | Always safe; initial value provides a default result. | Unsafe for empty collections; will throw an exception. |
In LINQ, they are combined into one overloaded method Aggregate. Below is one exmaple I wrote to showcase how to use it.
using Mono.Cecil;
using Mono.CompilerServices.SymbolWriter;
using System;
using System.IO;
using System.Reflection;
using System.Linq;
using System.Text;
class Program
{
static void Main()
{
string[] typeCode = ["string","bool", "datetime","int"];
var typeCode2 = (string[])typeCode.Clone(); ;
typeCode2[0] = $@"{{ ""code"": ""{typeCode2[0]}"" }}";
var result = typeCode.AsEnumerable().Aggregate(new StringBuilder(),
(a, b) => a.Append(@$"{{ ""code"": ""{b}"" }},"));
var result2 = typeCode.AsEnumerable().Aggregate(
(a, b) => @$"{a},{{ ""code"": ""{b}"" }}");
var result3 = typeCode2.AsEnumerable().Aggregate(
(a, b) => @$"{a},{{ ""code"": ""{b}"" }}");
Console.WriteLine(result.ToString());
Console.WriteLine(result2.ToString());
Console.WriteLine(result3.ToString());
/*
* { "code": "string" },{ "code": "bool" },{ "code": "datetime" },{ "code": "int" },
* string,{ "code": "bool" },{ "code": "datetime" },{ "code": "int" }
* { "code": "string" },{ "code": "bool" },{ "code": "datetime" },{ "code": "int" }
*/
}
}