From c5435f482ff3efd857f4dec8d3f02e98c0f5e779 Mon Sep 17 00:00:00 2001 From: Mike Marynowski Date: Thu, 7 Mar 2024 01:35:18 -0500 Subject: [PATCH] Impl SortedMoneySet.TransformValues with nullable outputs, add tests --- .../SortedMoneySet.cs | 31 ++++++++++++++- .../SortedMoneySetTests/TransformValues.cs | 39 +++++++++++++++++-- 2 files changed, 65 insertions(+), 5 deletions(-) diff --git a/Source/Singulink.Globalization.Currency/SortedMoneySet.cs b/Source/Singulink.Globalization.Currency/SortedMoneySet.cs index fe70cd2..d29aa95 100644 --- a/Source/Singulink.Globalization.Currency/SortedMoneySet.cs +++ b/Source/Singulink.Globalization.Currency/SortedMoneySet.cs @@ -409,6 +409,8 @@ public void TransformValues(Func transform) if (Count == 0) return; + // TODO: Optimize if no values change. + foreach (var kvp in _amountLookup.ToList()) { decimal newAmount = transform(new Money(kvp.Value, kvp.Key)); @@ -420,6 +422,31 @@ public void TransformValues(Func transform) } } + /// + /// Applies the specified transformation to each value's amount in this set. Values transformed to a amount are removed. + /// + public void TransformValues(Func transform) + { + if (Count == 0) + return; + + // TODO: Optimize if no values change. + + foreach (var kvp in _amountLookup.ToList()) + { + decimal? newAmountOrNull = transform(new Money(kvp.Value, kvp.Key)); + + if (newAmountOrNull is not decimal newAmount) + { + _amountLookup.Remove(kvp.Key); + } + else if (newAmount != kvp.Value) + { + _amountLookup[kvp.Key] = newAmount; + } + } + } + /// /// Applies the specified transformation to each value's amount in this set. /// @@ -428,6 +455,8 @@ public void TransformAmounts(Func transform) if (Count == 0) return; + // TODO: Optimize if no values change. + foreach (var kvp in _amountLookup.ToList()) { decimal oldAmount = kvp.Value; @@ -472,7 +501,7 @@ public int TrimZeroAmounts() { List currenciesToRemove = null; - foreach (var kvp in _amountLookup.ToList()) + foreach (var kvp in _amountLookup) { if (kvp.Value == 0) { diff --git a/Tests/Singulink.Globalization.Currency.Tests/SortedMoneySetTests/TransformValues.cs b/Tests/Singulink.Globalization.Currency.Tests/SortedMoneySetTests/TransformValues.cs index 09395f5..10dceec 100644 --- a/Tests/Singulink.Globalization.Currency.Tests/SortedMoneySetTests/TransformValues.cs +++ b/Tests/Singulink.Globalization.Currency.Tests/SortedMoneySetTests/TransformValues.cs @@ -11,7 +11,7 @@ public class TransformValues private readonly SortedMoneySet _set = ImmutableSet.ToSet(); [TestMethod] - public void AllAmountsTransformed_UpdatesValues() + public void NonNullOutput_AllAmountsTransformed_UpdatesValue() { _set.TransformValues(x => x.Amount * 2); _set.Count.ShouldBe(3); @@ -19,17 +19,48 @@ public void AllAmountsTransformed_UpdatesValues() } [TestMethod] - public void IdentityTransform_NoChange() + public void NonNullOutput_IdentityTransform_NoChange() { _set.TransformValues(x => x.Amount); _set.ShouldBe(ImmutableSet); } [TestMethod] - public void EmptySet_NoChange() + public void NonNullOutput_EmptySet_NoChange() { SortedMoneySet emptySet = []; emptySet.TransformValues(x => x.Amount * 2); emptySet.Count.ShouldBe(0); } -} \ No newline at end of file + + [TestMethod] + public void NullableOutput_AllAmountsTransformed_UpdatesValue() + { + _set.TransformValues(x => (decimal?)x.Amount * 2); + _set.Count.ShouldBe(3); + _set.ShouldBe([new(200m, "USD"), new(100m, "CAD"), new(50m, "EUR")]); + } + + [TestMethod] + public void NullableOutput_IdentityTransform_NoChange() + { + _set.TransformValues(x => (decimal?)x.Amount); + _set.ShouldBe(ImmutableSet); + } + + [TestMethod] + public void NullableOutput_EmptySet_NoChange() + { + SortedMoneySet emptySet = []; + emptySet.TransformValues(x => (decimal?)x.Amount * 2); + emptySet.Count.ShouldBe(0); + } + + [TestMethod] + public void NullableOutput_NullTransform_RemovesNullValues() + { + _set.TransformValues(x => x.Amount == 100m ? null : x.Amount); + _set.Count.ShouldBe(2); + _set.ShouldBe([new(50m, "CAD"), new(25m, "EUR")]); + } +}