From 6926215e505bc5f36eb138cbec07a3c36c1dc1f1 Mon Sep 17 00:00:00 2001
From: ilya-krivtsov <180809461+ilya-krivtsov@users.noreply.github.com>
Date: Fri, 11 Apr 2025 22:22:37 +0300
Subject: [PATCH 1/3] Map, Filter, Fold (hw7 - funcs)
---
.../Functions.Tests/Functions.Tests.csproj | 28 +++++
Functions/Functions.sln | 28 +++++
Functions/Functions/Functions.cs | 110 ++++++++++++++++++
Functions/Functions/Functions.csproj | 10 ++
4 files changed, 176 insertions(+)
create mode 100644 Functions/Functions.Tests/Functions.Tests.csproj
create mode 100644 Functions/Functions.sln
create mode 100644 Functions/Functions/Functions.cs
create mode 100644 Functions/Functions/Functions.csproj
diff --git a/Functions/Functions.Tests/Functions.Tests.csproj b/Functions/Functions.Tests/Functions.Tests.csproj
new file mode 100644
index 0000000..12e42e8
--- /dev/null
+++ b/Functions/Functions.Tests/Functions.Tests.csproj
@@ -0,0 +1,28 @@
+
+
+
+ net9.0
+ latest
+ enable
+ enable
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Functions/Functions.sln b/Functions/Functions.sln
new file mode 100644
index 0000000..a19ec08
--- /dev/null
+++ b/Functions/Functions.sln
@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.31903.59
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Functions", "Functions\Functions.csproj", "{E71A4E78-9D6C-4616-9F99-3B067B9B92F3}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Functions.Tests", "Functions.Tests\Functions.Tests.csproj", "{D1AAD59B-65F4-4F94-B960-24C9DE9C1BB8}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {E71A4E78-9D6C-4616-9F99-3B067B9B92F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E71A4E78-9D6C-4616-9F99-3B067B9B92F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E71A4E78-9D6C-4616-9F99-3B067B9B92F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E71A4E78-9D6C-4616-9F99-3B067B9B92F3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D1AAD59B-65F4-4F94-B960-24C9DE9C1BB8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D1AAD59B-65F4-4F94-B960-24C9DE9C1BB8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D1AAD59B-65F4-4F94-B960-24C9DE9C1BB8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D1AAD59B-65F4-4F94-B960-24C9DE9C1BB8}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/Functions/Functions/Functions.cs b/Functions/Functions/Functions.cs
new file mode 100644
index 0000000..31d6bc6
--- /dev/null
+++ b/Functions/Functions/Functions.cs
@@ -0,0 +1,110 @@
+namespace Functions;
+
+///
+/// Utility class that contains Map, Filter and Fold functions.
+///
+public static class Functions
+{
+ ///
+ /// Maps all elements from to elements of type using function.
+ ///
+ /// Source type.
+ /// Type to map to.
+ /// Source to map.
+ /// Function that maps to .
+ /// Sequence of mapped elements.
+ public static IEnumerable Map(this IEnumerable source, Func map)
+ {
+ foreach (var item in source)
+ {
+ yield return map(item);
+ }
+ }
+
+ ///
+ /// Filters elements from that satisfy .
+ ///
+ /// Type of elements.
+ /// Source to filter.
+ /// Function that filters elements; if it returns , adds element to the result, otherwise, doesn't.
+ /// Sequence of filtered elements.
+ public static IEnumerable Filter(this IEnumerable source, Func predicate)
+ {
+ foreach (var item in source)
+ {
+ if (predicate(item))
+ {
+ yield return item;
+ }
+ }
+ }
+
+ ///
+ /// Folds all elements in into one element.
+ ///
+ /// Type of elements.
+ /// Source to fold.
+ /// Function that is used to accumulate result.
+ /// Accumulated value.
+ /// Sequence is empty.
+ public static T Fold(this IEnumerable source, Func folder)
+ {
+ var enumerator = source.GetEnumerator();
+
+ if (!enumerator.MoveNext())
+ {
+ throw new InvalidOperationException("No elements in source");
+ }
+
+ var value = enumerator.Current;
+
+ while (enumerator.MoveNext())
+ {
+ value = folder(value, enumerator.Current);
+ }
+
+ return value;
+ }
+
+ ///
+ /// Folds all elements in into one element.
+ ///
+ /// Type of elements in .
+ /// The type of accumulated value.
+ /// Source to fold.
+ /// Initial value of accumulated value.
+ /// Function that is used to accumulate result.
+ /// Accumulated value.
+ public static TResult Fold(this IEnumerable source, TResult initialValue, Func folder)
+ {
+ var value = initialValue;
+ foreach (var item in source)
+ {
+ value = folder(value, item);
+ }
+
+ return value;
+ }
+
+ ///
+ /// Folds all elements in into one element.
+ ///
+ /// Type of elements in .
+ /// The type of accumulated value.
+ /// The result type.
+ /// Source to fold.
+ /// Initial value of accumulated value.
+ /// Function that is used to accumulate result.
+ /// Function that is used to convert accumulated result.
+ /// Converted accumulated value.
+ public static TResult Fold(this IEnumerable source, TIntermediate initialValue, Func folder, Func map)
+ {
+ var value = initialValue;
+ foreach (var item in source)
+ {
+ value = folder(value, item);
+ }
+
+ return map(value);
+ }
+}
diff --git a/Functions/Functions/Functions.csproj b/Functions/Functions/Functions.csproj
new file mode 100644
index 0000000..bf05b58
--- /dev/null
+++ b/Functions/Functions/Functions.csproj
@@ -0,0 +1,10 @@
+
+
+
+ Library
+ net9.0
+ enable
+ enable
+
+
+
From 3a900c4a471474b162b179ee0718f27d7995d87d Mon Sep 17 00:00:00 2001
From: ilya-krivtsov <180809461+ilya-krivtsov@users.noreply.github.com>
Date: Fri, 30 May 2025 14:09:08 +0300
Subject: [PATCH 2/3] Added license header (hw7 - funcs)
---
Functions/Functions/Functions.cs | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/Functions/Functions/Functions.cs b/Functions/Functions/Functions.cs
index 31d6bc6..a640461 100644
--- a/Functions/Functions/Functions.cs
+++ b/Functions/Functions/Functions.cs
@@ -1,3 +1,7 @@
+//
+// Copyright (c) Ilya Krivtsov. All rights reserved.
+//
+
namespace Functions;
///
From 8fb3933c593e1c223adc6b2201b99c384f0b3384 Mon Sep 17 00:00:00 2001
From: ilya-krivtsov <180809461+ilya-krivtsov@users.noreply.github.com>
Date: Fri, 30 May 2025 14:12:21 +0300
Subject: [PATCH 3/3] Added tests (hw7 - funcs)
---
Functions/Functions.Tests/FunctionsTests.cs | 94 +++++++++++++++++++
.../Functions.Tests/GlobalSuppressions.cs | 11 +++
2 files changed, 105 insertions(+)
create mode 100644 Functions/Functions.Tests/FunctionsTests.cs
create mode 100644 Functions/Functions.Tests/GlobalSuppressions.cs
diff --git a/Functions/Functions.Tests/FunctionsTests.cs b/Functions/Functions.Tests/FunctionsTests.cs
new file mode 100644
index 0000000..134f2e6
--- /dev/null
+++ b/Functions/Functions.Tests/FunctionsTests.cs
@@ -0,0 +1,94 @@
+//
+// Copyright (c) Ilya Krivtsov. All rights reserved.
+//
+
+namespace Functions.Tests;
+
+public class FunctionsTests
+{
+ private static readonly IEnumerable NumberSequence = Enumerable.Range(0, 120);
+
+ [Test]
+ public void Map_ConvertsNumbersToString_SameAs_Select()
+ {
+ AssertMapBehavesSameAsSelect(NumberSequence, x => x.ToString());
+ }
+
+ [Test]
+ public void Map_ConvertsStringToNumbers_SameAs_Select()
+ {
+ AssertMapBehavesSameAsSelect(NumberSequence.Select(x => x.ToString()), int.Parse);
+ }
+
+ [Test]
+ public void Filter_SelectsNumbers_SameAs_Where()
+ {
+ AssertFilerBehavesSameAsWhere(NumberSequence, x => x % 2 == 0);
+ }
+
+ [Test]
+ public void Filter_SelectsStrings_SameAs_Where()
+ {
+ AssertFilerBehavesSameAsWhere(NumberSequence.Select(x => x.ToString()), x => x.Contains('4'));
+ }
+
+ [Test]
+ public void Fold_SumsNumbers_SameAsAggregate()
+ {
+ static int Sum(int x, int y) => x + y;
+
+ var aggregateResult = NumberSequence.Aggregate(Sum);
+ var foldResult = NumberSequence.Fold(Sum);
+
+ Assert.That(aggregateResult, Is.EqualTo(foldResult));
+ }
+
+ [Test]
+ public void Fold_AddsCharacters_SameAsAggregate()
+ {
+ static string Sum(string x, char y) => x + y;
+
+ var source = Enumerable.Range('0', '~' - '0').Select(x => (char)x);
+
+ var aggregateResult = source.Aggregate(string.Empty, Sum);
+ var foldResult = source.Fold(string.Empty, Sum);
+
+ Assert.That(aggregateResult, Is.EqualTo(foldResult));
+ }
+
+ [Test]
+ public void Fold_AddsCharactersAndReverses_SameAsAggregate()
+ {
+ static string Sum(string x, char y) => x + y;
+ static string Reverse(string s) => string.Concat(s.Reverse());
+
+ var source = Enumerable.Range('0', '~' - '0').Select(x => (char)x);
+
+ var aggregateResult = source.Aggregate(string.Empty, Sum, Reverse);
+ var foldResult = source.Fold(string.Empty, Sum, Reverse);
+
+ Assert.That(aggregateResult, Is.EqualTo(foldResult));
+ }
+
+ [Test]
+ public void Fold_Throws_OnEmptyCollection()
+ {
+ Assert.Throws(() => Enumerable.Range(0, 0).Fold((x, y) => x + y));
+ }
+
+ private static void AssertMapBehavesSameAsSelect(IEnumerable source, Func map)
+ {
+ var selectResult = source.Select(map);
+ var mapResult = source.Map(map);
+
+ Assert.That(selectResult.SequenceEqual(mapResult), Is.True);
+ }
+
+ private static void AssertFilerBehavesSameAsWhere(IEnumerable source, Func filter)
+ {
+ var whereResult = source.Where(filter);
+ var filterResult = source.Filter(filter);
+
+ Assert.That(whereResult.SequenceEqual(filterResult), Is.True);
+ }
+}
diff --git a/Functions/Functions.Tests/GlobalSuppressions.cs b/Functions/Functions.Tests/GlobalSuppressions.cs
new file mode 100644
index 0000000..909e036
--- /dev/null
+++ b/Functions/Functions.Tests/GlobalSuppressions.cs
@@ -0,0 +1,11 @@
+//
+// Copyright (c) Ilya Krivtsov. All rights reserved.
+//
+
+// This file is used by Code Analysis to maintain SuppressMessage
+// attributes that are applied to this project.
+// Project-level suppressions either have no target or are given
+// a specific target and scoped to a namespace, type, member, etc.
+using System.Diagnostics.CodeAnalysis;
+
+[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "This is tests project")]