mirror of https://github.com/tasks/tasks
Use natural ordering for lists and filters
parent
2f37c76d93
commit
1b35cd5dd4
@ -0,0 +1,114 @@
|
|||||||
|
package org.tasks.filters;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The Alphanum Algorithm is an improved sorting algorithm for strings
|
||||||
|
* containing numbers. Instead of sorting numbers in ASCII order like
|
||||||
|
* a standard sort, this algorithm sorts numbers in numeric order.
|
||||||
|
*
|
||||||
|
* The Alphanum Algorithm is discussed at http://www.DaveKoelle.com
|
||||||
|
*
|
||||||
|
* Released under the MIT License - https://opensource.org/licenses/MIT
|
||||||
|
*
|
||||||
|
* Copyright 2007-2017 David Koelle
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.todoroo.astrid.api.Filter;
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is an updated version with enhancements made by Daniel Migowski, Andre Bogus, and David
|
||||||
|
* Koelle. Updated by David Koelle in 2017.
|
||||||
|
*
|
||||||
|
* <p>To use this class: Use the static "sort" method from the java.util.Collections class:
|
||||||
|
* Collections.sort(your list, new AlphanumComparator());
|
||||||
|
*/
|
||||||
|
public class AlphanumComparator implements Comparator<Filter> {
|
||||||
|
private boolean isDigit(char ch) {
|
||||||
|
return ((ch >= 48) && (ch <= 57));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Length of string is passed in for improved efficiency (only need to calculate it once) * */
|
||||||
|
private String getChunk(String s, int slength, int marker) {
|
||||||
|
StringBuilder chunk = new StringBuilder();
|
||||||
|
char c = s.charAt(marker);
|
||||||
|
chunk.append(c);
|
||||||
|
marker++;
|
||||||
|
if (isDigit(c)) {
|
||||||
|
while (marker < slength) {
|
||||||
|
c = s.charAt(marker);
|
||||||
|
if (!isDigit(c)) break;
|
||||||
|
chunk.append(c);
|
||||||
|
marker++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while (marker < slength) {
|
||||||
|
c = s.charAt(marker);
|
||||||
|
if (isDigit(c)) break;
|
||||||
|
chunk.append(c);
|
||||||
|
marker++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return chunk.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int compare(Filter f1, Filter f2) {
|
||||||
|
String s1 = f1.listingTitle;
|
||||||
|
String s2 = f2.listingTitle;
|
||||||
|
if ((s1 == null) || (s2 == null)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int thisMarker = 0;
|
||||||
|
int thatMarker = 0;
|
||||||
|
int s1Length = s1.length();
|
||||||
|
int s2Length = s2.length();
|
||||||
|
|
||||||
|
while (thisMarker < s1Length && thatMarker < s2Length) {
|
||||||
|
String thisChunk = getChunk(s1, s1Length, thisMarker);
|
||||||
|
thisMarker += thisChunk.length();
|
||||||
|
|
||||||
|
String thatChunk = getChunk(s2, s2Length, thatMarker);
|
||||||
|
thatMarker += thatChunk.length();
|
||||||
|
|
||||||
|
// If both chunks contain numeric characters, sort them numerically
|
||||||
|
int result;
|
||||||
|
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
|
||||||
|
if (result == 0) {
|
||||||
|
for (int i = 0; i < thisChunkLength; i++) {
|
||||||
|
result = thisChunk.charAt(i) - thatChunk.charAt(i);
|
||||||
|
if (result != 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = thisChunk.compareTo(thatChunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result != 0) return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s1Length - s2Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue