mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-08 21:30:57 +00:00
# added a natural order comparator (i.e. "R9" < "R10")
This commit is contained in:
1 parent
b551592cfa
commit
ad6e4de5a1
2 files changed
+176
No files matched your search
@@ -2,6 +2,7 @@ package com.sap.sailing.domain.common.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
@@ -230,5 +231,80 @@ public class Util {
|
||||
return "[" + a + ", " + b + ", " + c + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Natural Order String Comparison inspired by the idea of Martin Pool and Dave Koelle.
|
||||
*
|
||||
* Natural order compares mixed (alphanumeric) string in a more intuitive way:
|
||||
* a < a0 < a1 < a1a < a1b < a2 < a10 < a20
|
||||
*
|
||||
*/
|
||||
public static class NaturalComparator implements Comparator<String> {
|
||||
|
||||
/**
|
||||
* Compare the passed strings in natural order.
|
||||
*/
|
||||
@Override
|
||||
public int compare(String a, String b) {
|
||||
int result = 0;
|
||||
int aIndex = 0;
|
||||
int bIndex = 0;
|
||||
int aLength = a.length();
|
||||
int bLength = b.length();
|
||||
|
||||
while(aIndex < aLength && bIndex < bLength) {
|
||||
// Get next block of all-char or all-digit substring
|
||||
String aBlock = getBlock(a, aIndex);
|
||||
aIndex += aBlock.length();
|
||||
String bBlock = getBlock(b, bIndex);
|
||||
bIndex += bBlock.length();
|
||||
|
||||
// Compare all-digit blocks as numbers - all-char blocks as strings
|
||||
if (Character.isDigit(aBlock.charAt(0)) && Character.isDigit(bBlock.charAt(0))) {
|
||||
result = Integer.valueOf(aBlock).compareTo(Integer.valueOf(bBlock));
|
||||
} else {
|
||||
result = aBlock.compareTo(bBlock);
|
||||
}
|
||||
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Strings may be of different size
|
||||
return aLength - bLength;
|
||||
}
|
||||
|
||||
private String getBlock(String value, int index) {
|
||||
int valueLength = value.length();
|
||||
StringBuilder blockBuilder = new StringBuilder();
|
||||
|
||||
char ch = value.charAt(index++);
|
||||
blockBuilder.append(ch);
|
||||
|
||||
if (Character.isDigit(ch)) {
|
||||
while (index < valueLength) {
|
||||
ch = value.charAt(index++);
|
||||
if (!Character.isDigit(ch)) {
|
||||
break;
|
||||
} else {
|
||||
blockBuilder.append(ch);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (index < valueLength) {
|
||||
ch = value.charAt(index++);
|
||||
if (Character.isDigit(ch)) {
|
||||
break;
|
||||
} else {
|
||||
blockBuilder.append(ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return blockBuilder.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
package com.sap.sailing.domain.common.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.domain.common.impl.Util.NaturalComparator;
|
||||
|
||||
public class NaturalComparatorTest {
|
||||
|
||||
private NaturalComparator comparator;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
comparator = new NaturalComparator();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmpty() {
|
||||
assertTrue(comparator.compare("", "a") < 0);
|
||||
assertTrue(comparator.compare("a", "") > 0);
|
||||
assertEquals(0, comparator.compare("", ""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleCharOrder() {
|
||||
assertTrue(comparator.compare("a", "b") < 0);
|
||||
assertTrue(comparator.compare("aa", "ab") < 0);
|
||||
assertTrue(comparator.compare("aaa", "aab") < 0);
|
||||
assertTrue(comparator.compare("aaa", "aaab") < 0);
|
||||
assertEquals(0, comparator.compare("abc", "abc"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleNumberOrder() {
|
||||
assertTrue(comparator.compare("0", "1") < 0);
|
||||
assertTrue(comparator.compare("00", "1") < 0);
|
||||
assertTrue(comparator.compare("2", "6") < 0);
|
||||
assertTrue(comparator.compare("9", "10") < 0);
|
||||
assertTrue(comparator.compare("9", "100") < 0);
|
||||
assertTrue(comparator.compare("198", "200") < 0);
|
||||
assertEquals(0, comparator.compare("0", "0"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCaseOrder() {
|
||||
assertTrue(comparator.compare("A", "a") < 0);
|
||||
assertTrue(comparator.compare("Z", "a") < 0);
|
||||
assertEquals(0, comparator.compare("AbCd123", "AbCd123"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLeadingOrder() {
|
||||
assertTrue(comparator.compare("0001", "002") < 0);
|
||||
assertTrue(comparator.compare(" 0 0 1", "2") < 0);
|
||||
assertTrue(comparator.compare("002b", "2c") < 0);
|
||||
assertTrue(comparator.compare("001a", "0001a") < 0);
|
||||
assertTrue(comparator.compare("0001a", "001b") < 0);
|
||||
assertEquals(0, comparator.compare("01", "01"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDigitVsCharOrder() {
|
||||
assertTrue(comparator.compare("0", "a") < 0);
|
||||
assertTrue(comparator.compare("0", "A") < 0);
|
||||
assertTrue(comparator.compare("9", "a") < 0);
|
||||
assertTrue(comparator.compare("9", "A") < 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMixedOrder() {
|
||||
assertTrue(comparator.compare("a42", "a300") < 0);
|
||||
assertTrue(comparator.compare("a1b2c3d4e5", "a1b2c9d4e5") < 0);
|
||||
assertTrue(comparator.compare("a1b2c3d4e5", "a1b2z3d4e5") < 0);
|
||||
|
||||
assertTrue(comparator.compare("a1b2 c3d4e5", "a1b2c3d4e5") < 0);
|
||||
|
||||
assertTrue(comparator.compare("a9b11", "a10b11") < 0);
|
||||
assertTrue(comparator.compare("a9b9", "a9b10") < 0);
|
||||
|
||||
assertTrue(comparator.compare("a12", "a123") < 0);
|
||||
assertTrue(comparator.compare("123", "1234") < 0);
|
||||
assertTrue(comparator.compare("12abc", "12abcd5") < 0);
|
||||
|
||||
assertTrue(comparator.compare("R1", "R10") < 0);
|
||||
assertTrue(comparator.compare("R 1", "R 10") < 0);
|
||||
assertTrue(comparator.compare("G1", "G10") < 0);
|
||||
assertTrue(comparator.compare("G 1", "G 10") < 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDotsOrder() {
|
||||
assertTrue(comparator.compare("0.1", "0.2") < 0);
|
||||
assertTrue(comparator.compare("0.01", "0.2") < 0);
|
||||
assertTrue(comparator.compare("0.1.5b", "0.2a") < 0);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user