From 73c7731031fb3d1b0d96b25e6fc1b2f4f8453ef5 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 3 Jan 2019 16:47:09 -0600 Subject: [PATCH] Natural compared case order --- Commons.Test/Util/NaturalComparerTests.cs | 5 +++- Commons/Commons.csproj | 2 +- Commons/Util/NaturalComparer.cs | 31 ++++++++++++++++++++--- Commons/Util/NaturalComparerOptions.cs | 3 ++- 4 files changed, 34 insertions(+), 7 deletions(-) diff --git a/Commons.Test/Util/NaturalComparerTests.cs b/Commons.Test/Util/NaturalComparerTests.cs index 90e5524..37eaf79 100644 --- a/Commons.Test/Util/NaturalComparerTests.cs +++ b/Commons.Test/Util/NaturalComparerTests.cs @@ -21,7 +21,8 @@ public enum ComparerEquality [InlineData("a", "b", ComparerEquality.LessThan)] [InlineData("b", "a", ComparerEquality.GreaterThan)] [InlineData("a", "a", ComparerEquality.Equal)] - [InlineData("a", "A", ComparerEquality.GreaterThan)] + [InlineData("a", "A", ComparerEquality.GreaterThan, NaturalComparerOptions.LowercaseFirst)] + [InlineData("A", "a", ComparerEquality.GreaterThan)] //single number & character [InlineData("4", "a", ComparerEquality.LessThan)] [InlineData("a", "4", ComparerEquality.GreaterThan)] @@ -72,6 +73,8 @@ public enum ComparerEquality [InlineData("aa", " aa", ComparerEquality.Equal, NaturalComparerOptions.IgnoreWhiteSpace)] [InlineData("aa ", " aa", ComparerEquality.Equal, NaturalComparerOptions.IgnoreWhiteSpace)] [InlineData("aa", " a\ta", ComparerEquality.Equal, NaturalComparerOptions.IgnoreWhiteSpace)] + //capitalization order + [InlineData("added4", "Added11", ComparerEquality.LessThan)] public void TestCompare(string left, string right, ComparerEquality expectedResult, NaturalComparerOptions options = NaturalComparerOptions.None) { var comparer = new NaturalComparer(options); diff --git a/Commons/Commons.csproj b/Commons/Commons.csproj index e75d261..874a278 100644 --- a/Commons/Commons.csproj +++ b/Commons/Commons.csproj @@ -6,7 +6,7 @@ true A collection of useful C# utilities, extensions, and data structures. Chris Gonzales - 1.0.2 + 1.0.3 Commons C# DataStructures Dictionary Extensions Copyright 2019 Chris Gonzales https://chrisg32.github.io/assets/cg_logo.png diff --git a/Commons/Util/NaturalComparer.cs b/Commons/Util/NaturalComparer.cs index 4cd2bed..96c5391 100644 --- a/Commons/Util/NaturalComparer.cs +++ b/Commons/Util/NaturalComparer.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions; -using CG.Commons.Extensions; namespace CG.Commons.Util { @@ -10,12 +9,14 @@ public class NaturalComparer : IComparer private readonly bool _ignoreCase; private readonly bool _ignoreWhitespace; private readonly bool _checkTrailingDecimalLength; + private readonly bool _lowercaseFirst; public NaturalComparer(NaturalComparerOptions options = NaturalComparerOptions.None) { _ignoreCase = options.HasFlag(NaturalComparerOptions.IgnoreCase); _ignoreWhitespace = options.HasFlag(NaturalComparerOptions.IgnoreWhiteSpace); _checkTrailingDecimalLength = options.HasFlag(NaturalComparerOptions.CheckTrailingDecimalLength); + _lowercaseFirst = options.HasFlag(NaturalComparerOptions.LowercaseFirst); } //less than zero = x is less than y @@ -27,7 +28,7 @@ public NaturalComparer(NaturalComparerOptions options = NaturalComparerOptions.N /// /// The left string to compare. /// The right string to compare. - /// If the right string is less than the left the return value will be less than zero. + /// If the left string is less than the right the return value will be less than zero. /// If the left string is greater than the right than a value greater than zero is returned. /// If the left string is equal to the right string zero is returned. public int Compare(string left, string right) @@ -95,13 +96,35 @@ public int Compare(string left, string right) if (yIsNum) return 1; //both characters are not numeric so we simply compare - var cresult = xchar.CompareTo(ychar); + var cresult = CapitalOrderComparison(xchar, ychar); if (cresult != 0) return cresult; } } - private string GetNumericString(IReadOnlyList source, ref int index) + private int CapitalOrderComparison(char x, char y) + { + var result = x.CompareTo(y); + if (result == 0) return result; + if (char.IsLetter(x) && char.IsLetter(y)) + { + result = char.ToLowerInvariant(x).CompareTo(char.ToLowerInvariant(y)); + if (result != 0) return result; + if (_lowercaseFirst) + { + if (!char.IsLower(x) && char.IsLower(y)) return -1; + if (char.IsLower(x) && !char.IsLower(y)) return 1; + } + else + { + if (!char.IsLower(x) && char.IsLower(y)) return 1; + if (char.IsLower(x) && !char.IsLower(y)) return -1; + } + } + return result; + } + + private static string GetNumericString(IReadOnlyList source, ref int index) { var sb = new StringBuilder(); while (index < source.Count && (char.IsDigit(source[index]) || source[index] == '.')) diff --git a/Commons/Util/NaturalComparerOptions.cs b/Commons/Util/NaturalComparerOptions.cs index b5f4bd8..c56f0af 100644 --- a/Commons/Util/NaturalComparerOptions.cs +++ b/Commons/Util/NaturalComparerOptions.cs @@ -8,6 +8,7 @@ public enum NaturalComparerOptions None, IgnoreCase, IgnoreWhiteSpace, - CheckTrailingDecimalLength + CheckTrailingDecimalLength, + LowercaseFirst } } \ No newline at end of file