diff --git a/SabreTools.Matching.Test/Compare/NaturalComparerTests.cs b/SabreTools.Matching.Test/Compare/NaturalComparerTests.cs
new file mode 100644
index 0000000..8aaf18d
--- /dev/null
+++ b/SabreTools.Matching.Test/Compare/NaturalComparerTests.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Linq;
+using SabreTools.Matching.Compare;
+using Xunit;
+
+namespace SabreTools.Matching.Test.Compare
+{
+ public class NaturalComparerTests
+ {
+ [Fact]
+ public void NaturalComparerListSortTest()
+ {
+ // Setup arrays
+ string[] sortable = ["0", "100", "5", "2", "1000"];
+ string[] expected = ["0", "2", "5", "100", "1000"];
+
+ // Run sorting on array
+ Array.Sort(sortable, new NaturalComparer());
+
+ // Check the output
+ Assert.True(sortable.SequenceEqual(expected));
+ }
+
+ [Fact]
+ public void NaturalReversedComparerListSortTest()
+ {
+ // Setup arrays
+ string[] sortable = ["0", "100", "5", "2", "1000"];
+ string[] expected = ["1000", "100", "5", "2", "0"];
+
+ // Run sorting on array
+ Array.Sort(sortable, new NaturalReversedComparer());
+
+ // Check the output
+ Assert.True(sortable.SequenceEqual(expected));
+ }
+ }
+}
\ No newline at end of file
diff --git a/SabreTools.Matching.Test/Compare/NaturalComparerUtilTests.cs b/SabreTools.Matching.Test/Compare/NaturalComparerUtilTests.cs
new file mode 100644
index 0000000..a50c73d
--- /dev/null
+++ b/SabreTools.Matching.Test/Compare/NaturalComparerUtilTests.cs
@@ -0,0 +1,59 @@
+using SabreTools.Matching.Compare;
+using Xunit;
+
+namespace SabreTools.Matching.Test.Compare
+{
+ public class NaturalComparerUtilTests
+ {
+ [Fact]
+ public void CompareNumericBothNullTest()
+ {
+ int actual = NaturalComparerUtil.CompareNumeric(null, null);
+ Assert.Equal(0, actual);
+ }
+
+ [Fact]
+ public void CompareNumericSingleNullTest()
+ {
+ int actual = NaturalComparerUtil.CompareNumeric(null, "notnull");
+ Assert.Equal(-1, actual);
+
+ actual = NaturalComparerUtil.CompareNumeric("notnull", null);
+ Assert.Equal(1, actual);
+ }
+
+ [Fact]
+ public void CompareNumericBothEqualTest()
+ {
+ int actual = NaturalComparerUtil.CompareNumeric("notnull", "notnull");
+ Assert.Equal(0, actual);
+ }
+
+ [Fact]
+ public void CompareNumericBothEqualWithPathTest()
+ {
+ int actual = NaturalComparerUtil.CompareNumeric("notnull/file.ext", "notnull/file.ext");
+ Assert.Equal(0, actual);
+ }
+
+ [Fact]
+ public void CompareNumericNumericNonDecimalStringTest()
+ {
+ int actual = NaturalComparerUtil.CompareNumeric("100", "10");
+ Assert.Equal(1, actual);
+
+ actual = NaturalComparerUtil.CompareNumeric("10", "100");
+ Assert.Equal(-1, actual);
+ }
+
+ [Fact]
+ public void CompareNumericNumericDecimalStringTest()
+ {
+ int actual = NaturalComparerUtil.CompareNumeric("100.100", "100.10");
+ Assert.Equal(1, actual);
+
+ actual = NaturalComparerUtil.CompareNumeric("100.10", "100.100");
+ Assert.Equal(-1, actual);
+ }
+ }
+}
\ No newline at end of file
diff --git a/SabreTools.Matching.Test/SabreTools.Matching.Test.csproj b/SabreTools.Matching.Test/SabreTools.Matching.Test.csproj
index db16aab..b910acd 100644
--- a/SabreTools.Matching.Test/SabreTools.Matching.Test.csproj
+++ b/SabreTools.Matching.Test/SabreTools.Matching.Test.csproj
@@ -3,6 +3,7 @@
net6.0;net8.0
false
+ latest
enable
diff --git a/SabreTools.Matching/Compare/NaturalComparer.cs b/SabreTools.Matching/Compare/NaturalComparer.cs
index a2e815f..b77e9b3 100644
--- a/SabreTools.Matching/Compare/NaturalComparer.cs
+++ b/SabreTools.Matching/Compare/NaturalComparer.cs
@@ -41,16 +41,17 @@ namespace SabreTools.Matching.Compare
else
return 0;
}
+
if (x.ToLowerInvariant() == y.ToLowerInvariant())
- {
return x.CompareTo(y);
- }
+
if (!table.TryGetValue(x, out string[]? x1))
{
//x1 = Regex.Split(x.Replace(" ", string.Empty), "([0-9]+)");
x1 = Regex.Split(x.ToLowerInvariant(), "([0-9]+)").Where(s => !string.IsNullOrEmpty(s)).ToArray();
table.Add(x, x1);
}
+
if (!table.TryGetValue(y, out string[]? y1))
{
//y1 = Regex.Split(y.Replace(" ", string.Empty), "([0-9]+)");
@@ -61,41 +62,28 @@ namespace SabreTools.Matching.Compare
for (int i = 0; i < x1.Length && i < y1.Length; i++)
{
if (x1[i] != y1[i])
- {
return PartCompare(x1[i], y1[i]);
- }
}
+
if (y1.Length > x1.Length)
- {
return 1;
- }
else if (x1.Length > y1.Length)
- {
return -1;
- }
else
- {
return x.CompareTo(y);
- }
}
private static int PartCompare(string left, string right)
{
if (!long.TryParse(left, out long x))
- {
return NaturalComparerUtil.CompareNumeric(left, right);
- }
if (!long.TryParse(right, out long y))
- {
return NaturalComparerUtil.CompareNumeric(left, right);
- }
// If we have an equal part, then make sure that "longer" ones are taken into account
if (x.CompareTo(y) == 0)
- {
return left.Length - right.Length;
- }
return x.CompareTo(y);
}
diff --git a/SabreTools.Matching/Compare/NaturalComparerUtil.cs b/SabreTools.Matching/Compare/NaturalComparerUtil.cs
index b907b23..80fcfc8 100644
--- a/SabreTools.Matching/Compare/NaturalComparerUtil.cs
+++ b/SabreTools.Matching/Compare/NaturalComparerUtil.cs
@@ -4,8 +4,21 @@ namespace SabreTools.Matching.Compare
{
public static class NaturalComparerUtil
{
- public static int CompareNumeric(string s1, string s2)
+ ///
+ /// Compare two strings by numeric parts
+ ///
+ public static int CompareNumeric(string? s1, string? s2)
{
+ // If both strings are null, return
+ if (s1 == null && s2 == null)
+ return 0;
+
+ // If one is null, then say that's less than
+ if (s1 == null)
+ return -1;
+ if (s2 == null)
+ return 1;
+
// Save the orginal strings, for later comparison
string s1orig = s1;
string s2orig = s2;
@@ -18,12 +31,6 @@ namespace SabreTools.Matching.Compare
if (s1 == s2)
return s1orig.CompareTo(s2orig);
- // If one is null, then say that's less than
- if (s1 == null)
- return -1;
- if (s2 == null)
- return 1;
-
// Now split into path parts after converting AltDirSeparator to DirSeparator
s1 = s1.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
s2 = s2.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
diff --git a/SabreTools.Matching/Compare/NaturalReversedComparer.cs b/SabreTools.Matching/Compare/NaturalReversedComparer.cs
index 0fe2698..f44eea0 100644
--- a/SabreTools.Matching/Compare/NaturalReversedComparer.cs
+++ b/SabreTools.Matching/Compare/NaturalReversedComparer.cs
@@ -41,16 +41,17 @@ namespace SabreTools.Matching.Compare
else
return 0;
}
+
if (y.ToLowerInvariant() == x.ToLowerInvariant())
- {
return y.CompareTo(x);
- }
+
if (!table.TryGetValue(x, out string[]? x1))
{
//x1 = Regex.Split(x.Replace(" ", string.Empty), "([0-9]+)");
x1 = Regex.Split(x.ToLowerInvariant(), "([0-9]+)").Where(s => !string.IsNullOrEmpty(s)).ToArray();
table.Add(x, x1);
}
+
if (!table.TryGetValue(y, out string[]? y1))
{
//y1 = Regex.Split(y.Replace(" ", string.Empty), "([0-9]+)");
@@ -61,41 +62,28 @@ namespace SabreTools.Matching.Compare
for (int i = 0; i < x1.Length && i < y1.Length; i++)
{
if (x1[i] != y1[i])
- {
return PartCompare(x1[i], y1[i]);
- }
}
+
if (y1.Length > x1.Length)
- {
return 1;
- }
else if (x1.Length > y1.Length)
- {
return -1;
- }
else
- {
return y.CompareTo(x);
- }
}
private static int PartCompare(string left, string right)
{
if (!long.TryParse(left, out long x))
- {
return NaturalComparerUtil.CompareNumeric(right, left);
- }
if (!long.TryParse(right, out long y))
- {
return NaturalComparerUtil.CompareNumeric(right, left);
- }
// If we have an equal part, then make sure that "longer" ones are taken into account
if (y.CompareTo(x) == 0)
- {
return right.Length - left.Length;
- }
return y.CompareTo(x);
}