Skip to content

Commit 0178e66

Browse files
authored
Merge pull request #10 from viruseg/dev
Performance Optimization
2 parents 50b56b4 + 48f4d29 commit 0178e66

1 file changed

Lines changed: 41 additions & 61 deletions

File tree

src/NaturalStringComparer/NaturalComparer.cs

Lines changed: 41 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ namespace GihanSoft.String;
99

1010
using System;
1111
using System.Collections.Generic;
12-
using System.Numerics;
1312

1413
/// <summary>
1514
/// Natural Comparer.
@@ -84,30 +83,7 @@ public static int Compare(ReadOnlySpan<char> x, ReadOnlySpan<char> y, StringComp
8483
var xOut = GetNumber(x.Slice(i), out var xNumAsSpan);
8584
var yOut = GetNumber(y.Slice(i), out var yNumAsSpan);
8685

87-
int compareResult;
88-
89-
if (IsUlong(xNumAsSpan) && IsUlong(yNumAsSpan))
90-
{
91-
#if NETSTANDARD2_1_OR_GREATER || NET8_0_OR_GREATER
92-
var xNum = ulong.Parse(xNumAsSpan);
93-
var yNum = ulong.Parse(yNumAsSpan);
94-
#else
95-
var xNum = ulong.Parse(xNumAsSpan.ToString());
96-
var yNum = ulong.Parse(yNumAsSpan.ToString());
97-
#endif
98-
compareResult = xNum.CompareTo(yNum);
99-
}
100-
else
101-
{
102-
#if NETSTANDARD2_1_OR_GREATER || NET8_0_OR_GREATER
103-
var xNum = BigInteger.Parse(xNumAsSpan);
104-
var yNum = BigInteger.Parse(yNumAsSpan);
105-
#else
106-
var xNum = BigInteger.Parse(xNumAsSpan.ToString());
107-
var yNum = BigInteger.Parse(yNumAsSpan.ToString());
108-
#endif
109-
compareResult = xNum.CompareTo(yNum);
110-
}
86+
var compareResult = CompareNumValues(xNumAsSpan, yNumAsSpan);
11187

11288
if (compareResult != 0)
11389
{
@@ -116,10 +92,6 @@ public static int Compare(ReadOnlySpan<char> x, ReadOnlySpan<char> y, StringComp
11692

11793
i = -1;
11894
length = Math.Min(xOut.Length, yOut.Length);
119-
if (length == 0 && xOut.Length == yOut.Length && x.Length != y.Length)
120-
{
121-
return y.Length < x.Length ? -1 : 1; // "033" < "33" === true
122-
}
12395

12496
x = xOut;
12597
y = yOut;
@@ -135,38 +107,6 @@ public static int Compare(ReadOnlySpan<char> x, ReadOnlySpan<char> y, StringComp
135107
return x.Length.CompareTo(y.Length);
136108
}
137109

138-
private static bool IsUlong(ReadOnlySpan<char> number)
139-
{
140-
while (number.Length > 0 && number[0] == '0')
141-
{
142-
number = number.Slice(1);
143-
}
144-
145-
// 18446744073709551615
146-
return number switch {
147-
{ Length: <= 19 } => true,
148-
{ Length: > 20 } => false,
149-
['1', < '8', ..] => true,
150-
['1', '8', < '4', ..] => true,
151-
['1', '8', '4', < '4', ..] => true,
152-
['1', '8', '4', '4', < '6', ..] => true,
153-
['1', '8', '4', '4', '6', < '7', ..] => true,
154-
['1', '8', '4', '4', '6', '7', < '4', ..] => true,
155-
['1', '8', '4', '4', '6', '7', '4', < '4', ..] => true,
156-
['1', '8', '4', '4', '6', '7', '4', '4', '0', < '7', ..] => true,
157-
['1', '8', '4', '4', '6', '7', '4', '4', '0', '7', < '3', ..] => true,
158-
['1', '8', '4', '4', '6', '7', '4', '4', '0', '7', '3', < '7', ..] => true,
159-
['1', '8', '4', '4', '6', '7', '4', '4', '0', '7', '3', '7', '0', < '9', ..] => true,
160-
['1', '8', '4', '4', '6', '7', '4', '4', '0', '7', '3', '7', '0', '9', < '5', ..] => true,
161-
['1', '8', '4', '4', '6', '7', '4', '4', '0', '7', '3', '7', '0', '9', '5', < '5', ..] => true,
162-
['1', '8', '4', '4', '6', '7', '4', '4', '0', '7', '3', '7', '0', '9', '5', '5', '0', ..] => true,
163-
['1', '8', '4', '4', '6', '7', '4', '4', '0', '7', '3', '7', '0', '9', '5', '5', '1', < '6', ..] => true,
164-
['1', '8', '4', '4', '6', '7', '4', '4', '0', '7', '3', '7', '0', '9', '5', '5', '1', '6', '0', ..] => true,
165-
['1', '8', '4', '4', '6', '7', '4', '4', '0', '7', '3', '7', '0', '9', '5', '5', '1', '6', '1', <= '5'] => true,
166-
_ => false
167-
};
168-
}
169-
170110
private static ReadOnlySpan<char> GetNumber(ReadOnlySpan<char> span, out ReadOnlySpan<char> number)
171111
{
172112
var i = 0;
@@ -178,4 +118,44 @@ private static ReadOnlySpan<char> GetNumber(ReadOnlySpan<char> span, out ReadOnl
178118
number = span.Slice(0, i);
179119
return span.Slice(i);
180120
}
121+
122+
private static int CompareNumValues(ReadOnlySpan<char> numValue1, ReadOnlySpan<char> numValue2)
123+
{
124+
var num1AsSpan = TrimZero(numValue1);
125+
var num2AsSpan = TrimZero(numValue2);
126+
127+
if (num1AsSpan.Length < num2AsSpan.Length)
128+
{
129+
return -1;
130+
}
131+
132+
if (num1AsSpan.Length > num2AsSpan.Length)
133+
{
134+
return 1;
135+
}
136+
137+
var compareResult = num1AsSpan.CompareTo(num2AsSpan, StringComparison.Ordinal);
138+
139+
if (compareResult != 0)
140+
{
141+
return Math.Sign(compareResult);
142+
}
143+
144+
if (numValue2.Length == numValue1.Length)
145+
{
146+
return compareResult;
147+
}
148+
149+
return numValue2.Length < numValue1.Length ? -1 : 1; // "033" < "33" === true
150+
}
151+
152+
private static ReadOnlySpan<char> TrimZero(ReadOnlySpan<char> numValue)
153+
{
154+
while (numValue.Length > 0 && numValue[0] == '0')
155+
{
156+
numValue = numValue.Slice(1);
157+
}
158+
159+
return numValue;
160+
}
181161
}

0 commit comments

Comments
 (0)