From 3d896ea5d10585f35e259473c6bb13c8933c502e Mon Sep 17 00:00:00 2001 From: Oliver Booth Date: Fri, 3 Jun 2022 11:53:40 +0100 Subject: [PATCH] Add IList.RemoveRange(Range) --- CHANGELOG.md | 1 + X10D.Tests/src/Collections/ListTests.cs | 72 +++++++++++++++++++------ X10D/src/Collections/ListExtensions.cs | 44 ++++++++++++++- X10D/src/ExceptionMessages.Designer.cs | 18 +++++++ X10D/src/ExceptionMessages.resx | 6 +++ 5 files changed, 125 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 427732f..5f32f28 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Added - X10D: Added `MathUtility.InverseLerp(float, float, float)` and `MathUtility.InverseLerp(double, double, double)` - X10D: Added `Circle`, `CircleF`, `Cuboid`, `Ellipse`, `EllipseF`, `Line3D`, `Line`, `LineF`, `Polygon`, `PolygonF`, `Polyhedron`, and `Sphere`, to complement System.Drawing structs such as `Point` and `Rectangle` +- X10D: Added `IList.RemoveRange(Range)` - X10D: Added `Point.ToSize()` - X10D: Added `Point.ToSizeF()` - X10D: Added `Point.ToVector2()` diff --git a/X10D.Tests/src/Collections/ListTests.cs b/X10D.Tests/src/Collections/ListTests.cs index f62adc4..87b9d20 100644 --- a/X10D.Tests/src/Collections/ListTests.cs +++ b/X10D.Tests/src/Collections/ListTests.cs @@ -79,6 +79,63 @@ public class ListTests Assert.ThrowsException(() => list!.Fill(0, 0, 0)); } + [TestMethod] + public void Random_ShouldReturnContainedObject_GivenNotNull() + { + var list = new List(Enumerable.Range(1, 52)); // 52! chance of being shuffled to the same order + int random = list.Random(); + + Assert.IsTrue(list.Contains(random)); + } + + [TestMethod] + public void Random_ShouldThrow_GivenNull() + { + Assert.ThrowsException(() => ((List?)null)!.Random()); + } + + [TestMethod] + public void RemoveRange_ShouldThrowArgumentNullException_GivenNull() + { + Assert.ThrowsException(() => ((List?)null)!.RemoveRange(new Range())); + } + + [TestMethod] + public void RemoveRange_ShouldThrowArgumentException_GivenEndIndexLessThanStart() + { + Assert.ThrowsException(() => new List().RemoveRange(2..0)); + } + + [TestMethod] + public void RemoveRange_ShouldThrowArgumentOutOfRangeException_GivenEndIndexGreaterThanOrEqualToCount() + { + Assert.ThrowsException(() => new List().RemoveRange(..0)); + Assert.ThrowsException(() => new List {1}.RemoveRange(..2)); + } + + [TestMethod] + public void RemoveRange_ShouldRemoveElements_GivenList() + { + var list = new List + { + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10 + }; + + Assert.AreEqual(10, list.Count); + list.RemoveRange(2..5); + Assert.AreEqual(6, list.Count); + CollectionAssert.AreEqual(new[] {1, 2, 7, 8, 9, 10}, list); + } + [TestMethod] public void Shuffle_ShouldReorder_GivenNotNull() { @@ -97,19 +154,4 @@ public class ListTests { Assert.ThrowsException(() => ((List?)null)!.Shuffle()); } - - [TestMethod] - public void Random_ShouldReturnContainedObject_GivenNotNull() - { - var list = new List(Enumerable.Range(1, 52)); // 52! chance of being shuffled to the same order - int random = list.Random(); - - Assert.IsTrue(list.Contains(random)); - } - - [TestMethod] - public void Random_ShouldThrow_GivenNull() - { - Assert.ThrowsException(() => ((List?)null)!.Random()); - } } diff --git a/X10D/src/Collections/ListExtensions.cs b/X10D/src/Collections/ListExtensions.cs index bb0b601..bd35d4b 100644 --- a/X10D/src/Collections/ListExtensions.cs +++ b/X10D/src/Collections/ListExtensions.cs @@ -1,4 +1,4 @@ -using System.Diagnostics.Contracts; +using System.Diagnostics.Contracts; using X10D.Core; namespace X10D.Collections; @@ -119,6 +119,48 @@ public static class ListExtensions return random.NextFrom(source); } + /// + /// Removes a range of elements from the list. + /// + /// The list whose elements to remove. + /// The range of elements to remove. + /// The type of the elements in . + /// is . + /// defines an invalid range. + /// + /// defines an end index whose value is greater than or equal to the count of elements in the + /// list. + /// + public static void RemoveRange(this IList source, Range range) + { +#if NET6_0_OR_GREATER + ArgumentNullException.ThrowIfNull(source); +#else + if (source is null) + { + throw new ArgumentNullException(nameof(source)); + } +#endif + + int start = range.Start.IsFromEnd ? source.Count - range.Start.Value : range.Start.Value; + int end = range.End.IsFromEnd ? source.Count - range.End.Value : range.End.Value; + + if (end < start) + { + throw new ArgumentException(ExceptionMessages.EndIndexLessThanStartIndex); + } + + if (end >= source.Count) + { + throw new ArgumentOutOfRangeException(nameof(range), ExceptionMessages.EndIndexGreaterThanCount); + } + + for (int index = end; index >= start; index--) + { + source.RemoveAt(index); + } + } + /// /// Reorganizes the elements in a list by implementing a Fisher-Yates shuffle. /// diff --git a/X10D/src/ExceptionMessages.Designer.cs b/X10D/src/ExceptionMessages.Designer.cs index 7a62adb..7dd2526 100644 --- a/X10D/src/ExceptionMessages.Designer.cs +++ b/X10D/src/ExceptionMessages.Designer.cs @@ -78,6 +78,24 @@ namespace X10D { } } + /// + /// Looks up a localized string similar to The end index must be less than the list count.. + /// + internal static string EndIndexGreaterThanCount { + get { + return ResourceManager.GetString("EndIndexGreaterThanCount", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The end index must be greater than or equal to the start index.. + /// + internal static string EndIndexLessThanStartIndex { + get { + return ResourceManager.GetString("EndIndexLessThanStartIndex", resourceCulture); + } + } + /// /// Looks up a localized string similar to HashAlgorithm's Create method returned null reference.. /// diff --git a/X10D/src/ExceptionMessages.resx b/X10D/src/ExceptionMessages.resx index e5beb21..c2bbd2e 100644 --- a/X10D/src/ExceptionMessages.resx +++ b/X10D/src/ExceptionMessages.resx @@ -26,6 +26,12 @@ The buffer is too small to contain the data. + + The end index must be greater than or equal to the start index. + + + The end index must be less than the list count. + {0} is not a class.