natsort icon indicating copy to clipboard operation
natsort copied to clipboard

Comparison fails with 00

Open PaulWoitaschek opened this issue 10 years ago • 1 comments

First of all thanks for your work.

We use it in MaterialAudiobookPlayer to compare file names. But recently a problem came up.

When a String start with zeros, the ordering gets wrong. I wrote a small unit test to demonstrate it here.

String first = "00 I";
String second = "01 I";
assertTrue(NaturalOrderComparator.naturalCompare(first, second) < 0);

This one fails.

PaulWoitaschek avatar Oct 18 '15 19:10 PaulWoitaschek

@PaulWoitaschek : Your repo issue says it was "Fixed" and you closed your issue.

Has this been fixed in the natsort code ?

I ask because I see an error in the pure Ruby implementation given as "natcmp.rb". It appears to have been written prior to the release of Ruby 2.0. The if statement at line 58 will always be true.

This will occur because String#[] was changed to return the single character at position 0 in Ruby 2.0. So the expression will be comparing a single character string against an integer, which will be false for == and true for !=. (ie, Ruby's object identity comparison.)

Prior to 2.0 String#[] returned the ordinal of the ASCII character at the given position only if 1 integer argument was given. All other scenarios with other kinds and numbers of arguments returned substring results. This was intensely disliked, hence the change.

For Ruby 2.x and higher, the following will work:

        if (num1[0].ord != 48) and (num2[0].ord != 48)

The following (listed from likely fastest to slowest) should work in all versions:

        if (num1[0,1] != '0') and (num2[0,1] != '0') # Ruby all versions

... OR ...

        if (num1[0,1] != 48.chr) and (num2[0,1] != 48.chr) # Ruby all versions

... OR ...

        if !(num1 =~ /^0/) and !(num2 =~ /^0/) # Ruby all versions

DanRathbun avatar Aug 05 '21 08:08 DanRathbun