Skip to content

Commit

Permalink
Improve FilteredComparators for Strings.
Browse files Browse the repository at this point in the history
  • Loading branch information
tommyettinger committed Dec 8, 2023
1 parent 9907cc8 commit f720966
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package com.github.tommyettinger.ds.support.sort;

import com.github.tommyettinger.ds.CharFilter;
import com.github.tommyettinger.function.CharPredicate;
import com.github.tommyettinger.function.CharToCharFunction;
import com.github.tommyettinger.function.ObjPredicate;
Expand All @@ -38,6 +39,14 @@ private FilteredComparators () {

}

public static Comparator<String> makeStringComparator(final CharFilter filter) {
return makeStringComparator(filter.filter, filter.editor);
}

public static Comparator<String> makeStringComparator(final CharComparator baseComparator, final CharFilter filter) {
return makeStringComparator(baseComparator, filter.filter, filter.editor);
}

public static Comparator<String> makeStringComparator(final CharPredicate filter, final CharToCharFunction editor) {
return (String l, String r) -> {
int llen = l.length(), rlen = r.length(), countL = llen, countR = rlen;
Expand Down Expand Up @@ -70,6 +79,47 @@ public static Comparator<String> makeStringComparator(final CharPredicate filter
};
}

/**
* Like {@link #makeStringComparator(CharPredicate, CharToCharFunction)}, but takes a base comparator that compare char items
* in a non-ascending order if needed. Another option could be to call the other makeStringComparator() and reverse the
* Comparator it returns.
* @param baseComparator a CharComparator that will be used to compare individual chars, not Strings
* @param filter a CharPredicate that should return true iff a character should be considered for equality/hashing
* @param editor a CharToCharFunction that will take a char from a key String and return a potentially different char
* @return a Comparator for Strings that will respect the given filter, editor, and base comparator
*/
public static Comparator<String> makeStringComparator(final CharComparator baseComparator, final CharPredicate filter, final CharToCharFunction editor) {
return (String l, String r) -> {
int llen = l.length(), rlen = r.length(), countL = llen, countR = rlen;
int cl = -1, cr = -1;
int i = 0, j = 0;
char el, er;
while (i < llen || j < rlen) {
if (i == llen) {
cl = -1;
}
else {
while (i < llen && !filter.test((char)(cl = l.charAt(i++)))) {
cl = -1;
countL--;
}
}
if (j == rlen) {
cr = -1;
}
else {
while (j < rlen && !filter.test((char)(cr = r.charAt(j++)))) {
cr = -1;
countR--;
}
}
if (cl != cr && (el = editor.applyAsChar((char)cl)) != (er = editor.applyAsChar((char)cr)))
return baseComparator.compare(el, er) * ((cl ^ cr) >> 31 | 1);
}
return countL - countR;
};
}

/**
* Creates a new Comparator that will respect a filter and an editor; it will be able to compare
* any {@link Iterable} of T with any other Iterable of T. The filter is an {@link ObjPredicate} of T items
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@
*/

/**
* Code for customized sorting on primitive arrays and collections. This is Apache-licensed code from the
* <a href="https://github.com/vigna/fastutil">FastUtil project</a> with minimal changes. Like fastutil,
* jdkgdxds is Apache-licensed, but if you want to refer to FastUtil's license,
* Code for customized sorting on primitive arrays and collections. With some exceptions (namely,
* {@link com.github.tommyettinger.ds.support.sort.ObjectComparators#comparingFloat(com.github.tommyettinger.function.ObjToFloatFunction)},
* {@link com.github.tommyettinger.ds.support.sort.NaturalTextComparator}, and
* {@link com.github.tommyettinger.ds.support.sort.FilteredComparators}, which are original to jdkgdxds), this is
* Apache-licensed code from the <a href="https://github.com/vigna/fastutil">FastUtil project</a> with minimal changes.
* Like fastutil, jdkgdxds is Apache-licensed, but if you want to refer to FastUtil's license,
* <a href="https://github.com/vigna/fastutil/blob/2411defb3b1bd7f004ea75a7706ccaebb4dbfc25/LICENSE-2.0">it is here</a>.
*/

Expand Down

0 comments on commit f720966

Please sign in to comment.