I'm trying to implement a search bar in which the user sends a search term and the search bar displays the results.
I have a naive solution which separates the original list into three sublists: a list with all the exact matches, a list with all the phrases containing the search term and a list with all the phrases that doesn't match. Later on I sort the unmatched list using Edit Distance algorithm.
Is this the right way to do it or should I concern a different approach such as suffix trees, etc. ?
public static <T> List<T> sortListByName(final String name, final List<T> itemsList,
final Function<T, String> itemNameExtractor, int limit) {
List<T> res = new LinkedList<>();
List<T> containedList = new LinkedList<>();
List<T> unmatchedList = new LinkedList<>();
// First, separates the list into sublists which have exact word match; the search term is a
// substring; the search term doesn't appear at all.
for (T item : itemsList) {
String currItemName = itemNameExtractor.apply(item);
if (currItemName.contains(name)) {
boolean isExactMatch = false;
for (String term : currItemName.split(" ")) {
if (term.equals(name)) {
res.add(item);
isExactMatch = true;
break;
}
}
if (!isExactMatch) {
containedList.add(item);
}
} else {
unmatchedList.add(item);
}
}
Comparator<T> comparator = new Comparator<T>() {
@Override
public int compare(final T t1, final T t2) {
Integer n1Length = itemNameExtractor.apply(t1).length();
Integer n2Length = itemNameExtractor.apply(t2).length();
return n1Length.compareTo(n2Length);
}
};
Collections.sort(res, comparator);
Collections.sort(containedList, comparator);
res.addAll(containedList);
if (res.size() >= limit) {
return res.subList(0, limit);
}
// Sort unmatched items by their edit distance rank and concatenate them to the contained
// matches list.
List<T> editDistList = EditDist.sortList(name, unmatchedList, itemNameExtractor);
res.addAll(editDistList);
if (res.size() > limit) {
return res.subList(0, limit);
}
return res;
}