mirror of
https://github.com/nextcloud/android.git
synced 2024-11-27 09:39:25 +03:00
Natural sorting, for digits use value (01 -> 1), order by leading zeros (1 > 01)
Signed-off-by: tobiasKaminsky <tobias@kaminsky.me>
This commit is contained in:
parent
6b000595b1
commit
c5d492cee9
2 changed files with 53 additions and 14 deletions
|
@ -27,6 +27,7 @@ package third_parties.daveKoeller;
|
|||
import com.owncloud.android.datamodel.OCFile;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.Serializable;
|
||||
import java.text.Collator;
|
||||
import java.util.Comparator;
|
||||
import java.util.Locale;
|
||||
|
@ -47,7 +48,7 @@ import java.util.Locale;
|
|||
* https://github.com/nextcloud/server/blob/9a4253ef7c34f9dc71a6a9f7828a10df769f0c32/tests/lib/NaturalSortTest.php
|
||||
* by Tobias Kaminsky
|
||||
*/
|
||||
public class AlphanumComparator<T> implements Comparator<T> {
|
||||
public class AlphanumComparator<T> implements Comparator<T>, Serializable {
|
||||
private boolean isDigit(char ch) {
|
||||
return ch >= 48 && ch <= 57;
|
||||
}
|
||||
|
@ -120,17 +121,48 @@ public class AlphanumComparator<T> implements Comparator<T> {
|
|||
// If both chunks contain numeric characters, sort them numerically
|
||||
int result = 0;
|
||||
if (isDigit(thisChunk.charAt(0)) && isDigit(thatChunk.charAt(0))) {
|
||||
// Simple chunk comparison by length.
|
||||
int thisChunkLength = thisChunk.length();
|
||||
result = thisChunkLength - thatChunk.length();
|
||||
// If equal, the first different number counts
|
||||
// extract digits
|
||||
int thisChunkZeroCount = 0;
|
||||
boolean zero = true;
|
||||
int c = 0;
|
||||
while (c < (thisChunk.length()) && isDigit(thisChunk.charAt(c))) {
|
||||
if (zero) {
|
||||
if (Character.getNumericValue(thisChunk.charAt(c)) == 0) {
|
||||
thisChunkZeroCount++;
|
||||
} else {
|
||||
zero = false;
|
||||
}
|
||||
}
|
||||
c++;
|
||||
}
|
||||
int thisChunkValue = Integer.parseInt(thisChunk.substring(0, c));
|
||||
|
||||
int thatChunkZeroCount = 0;
|
||||
c = 0;
|
||||
zero = true;
|
||||
while (c < (thatChunk.length()) && isDigit(thatChunk.charAt(c))) {
|
||||
if (zero) {
|
||||
if (Character.getNumericValue(thatChunk.charAt(c)) == 0) {
|
||||
thatChunkZeroCount++;
|
||||
} else {
|
||||
zero = false;
|
||||
}
|
||||
}
|
||||
c++;
|
||||
}
|
||||
int thatChunkValue = Integer.parseInt(thatChunk.substring(0, c));
|
||||
|
||||
result = Integer.compare(thisChunkValue, thatChunkValue);
|
||||
|
||||
if (result == 0) {
|
||||
for (int i = 0; i < thisChunkLength; i++) {
|
||||
result = thisChunk.charAt(i) - thatChunk.charAt(i);
|
||||
// value is equal, compare leading zeros
|
||||
result = Integer.compare(thisChunkZeroCount, thatChunkZeroCount);
|
||||
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
} else if (isSpecialChar(thisChunk.charAt(0)) && isSpecialChar(thatChunk.charAt(0))) {
|
||||
for (int i = 0; i < thisChunk.length(); i++) {
|
||||
|
|
|
@ -43,10 +43,10 @@ public class TestSorting {
|
|||
@Test
|
||||
public void testSpecialChars() {
|
||||
|
||||
String[] unsortedArray = {"11 - November", "Test 04", "Test 01", "Ôle", "Üüü", "01 - Januar", "[Test] Folder",
|
||||
String[] unsortedArray = {"Test 1", "11 - November", "Test 04", "Test 01", "Ôle", "Üüü", "01 - January", "[Test] Folder",
|
||||
"z.[Test]", "z. Test"};
|
||||
|
||||
String[] sortedArray = {"[Test] Folder", "01 - Januar", "11 - November", "Ôle", "Test 01", "Test 04", "Üüü",
|
||||
String[] sortedArray = {"[Test] Folder", "01 - January", "11 - November", "Ôle", "Test 1", "Test 01", "Test 04", "Üüü",
|
||||
"z. Test", "z.[Test]"};
|
||||
|
||||
assertTrue(sortAndTest(unsortedArray, sortedArray));
|
||||
|
@ -60,6 +60,14 @@ public class TestSorting {
|
|||
assertTrue(sortAndTest(unsortedArray, sortedArray));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTrailingZeros() {
|
||||
String[] unsortedArray = {"T 3 abc", "T 2 abc", "T 03 abc", "T 01 abc", "T 0 abc", "T 02 abc", "T 1 abc", "T 001 abc", "T 000 abc", "T 00 abc"};
|
||||
String[] sortedArray = {"T 0 abc", "T 00 abc", "T 000 abc", "T 1 abc", "T 01 abc", "T 001 abc", "T 2 abc", "T 02 abc", "T 3 abc", "T 03 abc"};
|
||||
|
||||
assertTrue(sortAndTest(unsortedArray, sortedArray));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNumbers() {
|
||||
String[] unsortedArray = {"124.txt", "abc1", "123.txt", "abc", "abc2", "def (2).txt", "ghi 10.txt", "abc12",
|
||||
|
@ -99,7 +107,7 @@ public class TestSorting {
|
|||
List<String> sortedList = Arrays.asList(sortedArray);
|
||||
|
||||
|
||||
Collections.sort(unsortedList, new AlphanumComparator());
|
||||
Collections.sort(unsortedList, new AlphanumComparator<>());
|
||||
|
||||
for (int i = 0; i < sortedList.size(); i++) {
|
||||
if (sortedList.get(i).compareTo(unsortedList.get(i)) != 0) {
|
||||
|
@ -107,7 +115,6 @@ public class TestSorting {
|
|||
System.out.println(" target: " + sortedList.toString());
|
||||
System.out.println(" actual: " + unsortedList.toString());
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue