Skip to content

Commit

Permalink
Natural compared case order
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisg32 committed Jan 3, 2019
1 parent 84dbd17 commit 73c7731
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 7 deletions.
5 changes: 4 additions & 1 deletion Commons.Test/Util/NaturalComparerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion Commons/Commons.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Description>A collection of useful C# utilities, extensions, and data structures.</Description>
<Authors>Chris Gonzales</Authors>
<Version>1.0.2</Version>
<Version>1.0.3</Version>
<PackageTags>Commons C# DataStructures Dictionary Extensions</PackageTags>
<Copyright>Copyright 2019 Chris Gonzales</Copyright>
<PackageIconUrl>https://chrisg32.github.io/assets/cg_logo.png</PackageIconUrl>
Expand Down
31 changes: 27 additions & 4 deletions Commons/Util/NaturalComparer.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using CG.Commons.Extensions;

namespace CG.Commons.Util
{
Expand All @@ -10,12 +9,14 @@ public class NaturalComparer : IComparer<string>
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
Expand All @@ -27,7 +28,7 @@ public NaturalComparer(NaturalComparerOptions options = NaturalComparerOptions.N
/// </summary>
/// <param name="left">The left string to compare.</param>
/// <param name="right">The right string to compare.</param>
/// <returns>If the right string is less than the left the return value will be less than zero.
/// <returns>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.</returns>
public int Compare(string left, string right)
Expand Down Expand Up @@ -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<char> 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<char> source, ref int index)
{
var sb = new StringBuilder();
while (index < source.Count && (char.IsDigit(source[index]) || source[index] == '.'))
Expand Down
3 changes: 2 additions & 1 deletion Commons/Util/NaturalComparerOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public enum NaturalComparerOptions
None,
IgnoreCase,
IgnoreWhiteSpace,
CheckTrailingDecimalLength
CheckTrailingDecimalLength,
LowercaseFirst
}
}

0 comments on commit 73c7731

Please sign in to comment.