Skip to content

Commit 9b8d8e9

Browse files
Merge pull request #867 from pszklarska/fix_844
Fixing #844 - If a category has exact name entered, show it first
2 parents 7684826 + 0e2d2c1 commit 9b8d8e9

File tree

4 files changed

+106
-7
lines changed

4 files changed

+106
-7
lines changed

app/build.gradle

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,23 @@ dependencies {
1212
compile 'ch.acra:acra:4.7.0'
1313
compile 'org.mediawiki:api:1.3'
1414
compile 'commons-codec:commons-codec:1.10'
15+
compile 'com.github.pedrovgs:renderers:3.3.3'
16+
compile 'com.google.code.gson:gson:2.8.0'
17+
compile 'com.jakewharton.timber:timber:4.5.1'
18+
compile 'info.debatty:java-string-similarity:0.24'
19+
compile ('com.mapbox.mapboxsdk:mapbox-android-sdk:5.1.0@aar'){
20+
transitive=true
21+
}
22+
1523
compile "com.android.support:support-v4:${project.supportLibVersion}"
1624
compile "com.android.support:appcompat-v7:${project.supportLibVersion}"
1725
compile "com.android.support:design:${project.supportLibVersion}"
18-
compile 'com.google.code.gson:gson:2.8.0'
26+
1927
compile "com.jakewharton:butterknife:$BUTTERKNIFE_VERSION"
20-
compile 'com.github.pedrovgs:renderers:3.3.3'
2128
annotationProcessor "com.jakewharton:butterknife-compiler:$BUTTERKNIFE_VERSION"
22-
compile 'com.jakewharton.timber:timber:4.5.1'
29+
2330
compile 'com.squareup.okhttp3:okhttp:3.8.1'
2431
compile 'com.squareup.okio:okio:1.13.0'
25-
compile ('com.mapbox.mapboxsdk:mapbox-android-sdk:5.1.0@aar'){
26-
transitive=true
27-
}
2832

2933
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
3034
// Because RxAndroid releases are few and far between, it is recommended you also

app/src/main/java/fr/free/nrw/commons/category/CategorizationFragment.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
import java.util.ArrayList;
2727
import java.util.Calendar;
28+
import java.util.Comparator;
2829
import java.util.Date;
2930
import java.util.HashMap;
3031
import java.util.List;
@@ -36,6 +37,7 @@
3637
import fr.free.nrw.commons.R;
3738
import fr.free.nrw.commons.data.Category;
3839
import fr.free.nrw.commons.upload.MwVolleyApi;
40+
import fr.free.nrw.commons.utils.StringSortingUtils;
3941
import io.reactivex.Observable;
4042
import io.reactivex.android.schedulers.AndroidSchedulers;
4143
import io.reactivex.schedulers.Schedulers;
@@ -107,7 +109,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container,
107109

108110
RxTextView.textChanges(categoriesFilter)
109111
.takeUntil(RxView.detaches(categoriesFilter))
110-
.debounce(300, TimeUnit.MILLISECONDS)
112+
.debounce(500, TimeUnit.MILLISECONDS)
111113
.observeOn(AndroidSchedulers.mainThread())
112114
.subscribe(filter -> updateCategoryList(filter.toString()));
113115
return rootView;
@@ -200,6 +202,7 @@ private void updateCategoryList(String filter) {
200202
)
201203
.filter(categoryItem -> !containsYear(categoryItem.getName()))
202204
.distinct()
205+
.sorted(sortBySimilarity(filter))
203206
.observeOn(AndroidSchedulers.mainThread())
204207
.subscribe(
205208
s -> categoriesAdapter.add(s), Timber::e, () -> {
@@ -221,6 +224,12 @@ private void updateCategoryList(String filter) {
221224
);
222225
}
223226

227+
private Comparator<CategoryItem> sortBySimilarity(final String filter) {
228+
Comparator<String> stringSimilarityComparator = StringSortingUtils.sortBySimilarity(filter);
229+
return (firstItem, secondItem) -> stringSimilarityComparator
230+
.compare(firstItem.getName(), secondItem.getName());
231+
}
232+
224233
private List<String> getStringList(List<CategoryItem> input) {
225234
List<String> output = new ArrayList<>();
226235
for (CategoryItem item : input) {
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package fr.free.nrw.commons.utils;
2+
3+
import java.util.Comparator;
4+
5+
import info.debatty.java.stringsimilarity.Levenshtein;
6+
7+
public class StringSortingUtils {
8+
9+
private StringSortingUtils() {
10+
//no-op
11+
}
12+
13+
/**
14+
* Returns Comparator for sorting strings by its similarity with Levenshtein
15+
* algorithm. By using this Comparator we get results from the highest to
16+
* the lowest match.
17+
*
18+
* @param filter pattern to compare similarity
19+
* @return Comparator with string similarity
20+
*/
21+
22+
public static Comparator<String> sortBySimilarity(final String filter) {
23+
return (firstItem, secondItem) -> {
24+
double firstItemSimilarity = calculateSimilarity(firstItem, filter);
25+
double secondItemSimilarity = calculateSimilarity(secondItem, filter);
26+
return (int) Math.signum(secondItemSimilarity - firstItemSimilarity);
27+
};
28+
}
29+
30+
private static double calculateSimilarity(String firstString, String secondString) {
31+
String longer = firstString.toLowerCase();
32+
String shorter = secondString.toLowerCase();
33+
34+
if (firstString.length() < secondString.length()) {
35+
longer = secondString;
36+
shorter = firstString;
37+
}
38+
int longerLength = longer.length();
39+
if (longerLength == 0) {
40+
return 1.0;
41+
}
42+
43+
double distanceBetweenStrings = new Levenshtein().distance(longer, shorter);
44+
return (longerLength - distanceBetweenStrings) / (double) longerLength;
45+
}
46+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package fr.free.nrw.commons.utils;
2+
3+
import java.util.Arrays;
4+
import java.util.Collections;
5+
import java.util.List;
6+
import org.junit.Assert;
7+
import org.junit.Test;
8+
9+
public class StringSortingUtilsTest {
10+
11+
@Test
12+
public void testSortingNumbersBySimilarity() throws Exception {
13+
List<String> actualList = Arrays.asList("1234567", "4567", "12345", "123", "1234");
14+
List<String> expectedList = Arrays.asList("1234", "12345", "123", "1234567", "4567");
15+
16+
Collections.sort(actualList, StringSortingUtils.sortBySimilarity("1234"));
17+
Assert.assertEquals(expectedList, actualList);
18+
}
19+
20+
@Test
21+
public void testSortingTextBySimilarity() throws Exception {
22+
List<String> actualList = Arrays.asList("The quick brown fox",
23+
"quick brown fox",
24+
"The",
25+
"The quick ",
26+
"The fox",
27+
"brown fox",
28+
"fox");
29+
List<String> expectedList = Arrays.asList("The",
30+
"The fox",
31+
"The quick ",
32+
"The quick brown fox",
33+
"quick brown fox",
34+
"brown fox",
35+
"fox");
36+
37+
Collections.sort(actualList, StringSortingUtils.sortBySimilarity("The"));
38+
Assert.assertEquals(expectedList, actualList);
39+
}
40+
}

0 commit comments

Comments
 (0)