From 23e07b65b89b1302ebef45710c571fdbfe4d86d3 Mon Sep 17 00:00:00 2001 From: Oliver Booth Date: Thu, 12 May 2022 13:52:04 +0100 Subject: [PATCH] Add [ReadOnly]Span.Count(Predicate) --- CHANGELOG.md | 2 ++ X10D.Tests/src/Linq/ReadOnlySpanTests.cs | 24 +++++++++++++++ X10D.Tests/src/Linq/SpanTests.cs | 24 +++++++++++++++ X10D/src/Linq/ReadOnlySpanExtensions.cs | 39 ++++++++++++++++++++++++ X10D/src/Linq/SpanExtensions.cs | 39 ++++++++++++++++++++++++ 5 files changed, 128 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e227e0..ac2db5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,9 @@ - X10D: Added `IEnumerable.DisposeAll()` - X10D: Added `IEnumerable.DisposeAllAsync()` - X10D: Added `char.IsEmoji` +- X10D: Added `ReadOnlySpan.Count(Predicate)` - X10D: Added `Rune.IsEmoji` +- X10D: Added `Span.Count(Predicate)` - X10D: Added `string.IsEmoji` - X10D: Added `Vector2.WithX()` - X10D: Added `Vector2.WithY()` diff --git a/X10D.Tests/src/Linq/ReadOnlySpanTests.cs b/X10D.Tests/src/Linq/ReadOnlySpanTests.cs index e33f5cd..4f2cbd9 100644 --- a/X10D.Tests/src/Linq/ReadOnlySpanTests.cs +++ b/X10D.Tests/src/Linq/ReadOnlySpanTests.cs @@ -55,4 +55,28 @@ public class ReadOnlySpanTests return span.Any(null!); }); } + + [TestMethod] + public void Count_ShouldReturn0_GivenEmptySpan() + { + var span = new ReadOnlySpan(); + Assert.AreEqual(0, span.Count(i => i % 2 == 0)); + } + + [TestMethod] + public void Count_ShouldReturn5_ForEvenNumbers_GivenNumbers1To10() + { + var span = new ReadOnlySpan(new[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}); + Assert.AreEqual(5, span.Count(i => i % 2 == 0)); + } + + [TestMethod] + public void Count_ShouldThrow_GivenNullPredicate() + { + Assert.ThrowsException(() => + { + var span = new ReadOnlySpan(); + return span.Count(null!); + }); + } } diff --git a/X10D.Tests/src/Linq/SpanTests.cs b/X10D.Tests/src/Linq/SpanTests.cs index 98c5fe3..60882f4 100644 --- a/X10D.Tests/src/Linq/SpanTests.cs +++ b/X10D.Tests/src/Linq/SpanTests.cs @@ -55,4 +55,28 @@ public class SpanTests return span.Any(null!); }); } + + [TestMethod] + public void Count_ShouldReturn0_GivenEmptySpan() + { + var span = new Span(); + Assert.AreEqual(0, span.Count(i => i % 2 == 0)); + } + + [TestMethod] + public void Count_ShouldReturn5_ForEvenNumbers_GivenNumbers1To10() + { + var span = new Span(new[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}); + Assert.AreEqual(5, span.Count(i => i % 2 == 0)); + } + + [TestMethod] + public void Count_ShouldThrow_GivenNullPredicate() + { + Assert.ThrowsException(() => + { + var span = new Span(); + return span.Count(null!); + }); + } } diff --git a/X10D/src/Linq/ReadOnlySpanExtensions.cs b/X10D/src/Linq/ReadOnlySpanExtensions.cs index 8b10261..bf0d1d3 100644 --- a/X10D/src/Linq/ReadOnlySpanExtensions.cs +++ b/X10D/src/Linq/ReadOnlySpanExtensions.cs @@ -84,4 +84,43 @@ public static class ReadOnlySpanExtensions return false; } + + /// + /// Returns a number that represents how many elements in the specified sequence satisfy a condition. + /// + /// A that contains elements to be tested and counted. + /// A function to test each element for a condition. + /// The type of the elements in . + /// + /// A number that represents how many elements in the sequence satisfy the condition in the predicate function. + /// + /// is . + public static int Count(this ReadOnlySpan source, Predicate predicate) + { +#if NET6_0_OR_GREATER + ArgumentNullException.ThrowIfNull(predicate); +#else + if (predicate is null) + { + throw new ArgumentNullException(nameof(predicate)); + } +#endif + + if (source.IsEmpty) + { + return 0; + } + + var count = 0; + + foreach (TSource item in source) + { + if (predicate(item)) + { + count++; + } + } + + return count; + } } diff --git a/X10D/src/Linq/SpanExtensions.cs b/X10D/src/Linq/SpanExtensions.cs index d5a208a..ce2e3f3 100644 --- a/X10D/src/Linq/SpanExtensions.cs +++ b/X10D/src/Linq/SpanExtensions.cs @@ -84,4 +84,43 @@ public static class SpanExtensions return false; } + + /// + /// Returns a number that represents how many elements in the specified sequence satisfy a condition. + /// + /// A that contains elements to be tested and counted. + /// A function to test each element for a condition. + /// The type of the elements in . + /// + /// A number that represents how many elements in the sequence satisfy the condition in the predicate function. + /// + /// is . + public static int Count(this Span source, Predicate predicate) + { +#if NET6_0_OR_GREATER + ArgumentNullException.ThrowIfNull(predicate); +#else + if (predicate is null) + { + throw new ArgumentNullException(nameof(predicate)); + } +#endif + + if (source.IsEmpty) + { + return 0; + } + + var count = 0; + + foreach (TSource item in source) + { + if (predicate(item)) + { + count++; + } + } + + return count; + } }