Slow Search Ignoring Accents

2

I have a list of objects and I'm doing a title search.

I use Normalizer to make the comparison ignoring accents:

public static boolean containsIgnoreCaseAndAccents(String haystack, String needle) {
    final String hsToCompare = removeAccents(haystack).toLowerCase();
    final String nToCompare = removeAccents(needle).toLowerCase();

    return hsToCompare.contains(nToCompare);
}

public static String removeAccents(String string) {
    return ACCENTS_PATTERN.matcher(Normalizer.normalize(string, Normalizer.Form.NFD)).replaceAll("");
}

And the search:

for(Object o : allObjects){

            if(o.getTitle()!=null && containsIgnoreCaseAndAccents(o.getTitle(), text)) {
                searchObjects.add(o);
            }
}

The text I get from my EditText . It works, however there is a delay in this comparison, and the search gets slightly caught, giving a delay as you type each letter.

Is there any way to do this comparison faster?

    
asked by anonymous 17.09.2016 / 15:37

2 answers

3

For every "title" you check you are always removing the accents of the text to compare.

Only remove accents from the text once and use it for each comparison with the "title"

Use a class to make the comparisons:

public classe IgnoreCaseAndAccentsComparator{

    private String text;  

    IgnoreCaseAndAccentsComparator(String text){

        this.text = removeAccents(text).toLowerCase();
    }

    public boolean contains(String text){

        this.text.contains(removeAccents(text).toLowerCase());
    }

    //Se quiser pode adicionar outros métodos de comparação

    public static String removeAccents(String string) {
        return ACCENTS_PATTERN.matcher(Normalizer.normalize(string, Normalizer.Form.NFD)).replaceAll("");
    }
}

Use this:

IgnoreCaseAndAccentsComparator comparator = new IgnoreCaseAndAccentsComparator(text);

for(Object o : allObjects){

    if(o.getTitle()!=null && comparator.contains(o.getTitle())) {
        searchObjects.add(o);
    }
}

If the search is done while the text is typed, performance can be improved by using a "delay" between each call to the method so that it is not called by each letter entered but only after a pause in the intro.

Note: I just tried to optimize your code without questioning how the accents are removed, which can possibly be optimized as well.     

17.09.2016 / 16:14
0

My problem was that I had to search while the text was typed. As it was typed search, there are not many choices of accented letters. I used this answer ( link ) as a basis and did my method to replace the accented strings.

Looking like this:

public static String removeAccent(String lowerCaseString)
{
    String withAccent = "äáâàãéêëèíîïìöóôòõüúûùç";
    String withoutAccent = "aaaaaeeeeiiiiooooouuuuc";

    for (int i = 0; i < withAccent.length(); i++)
    {
        lowerCaseString = lowerCaseString.replace(withAccent.charAt(i), withoutAccent.charAt(i));
    }
    return lowerCaseString;
}

The performance was good and works for the keyboard accents of Android, because the searches will be done in Portuguese.

    
17.09.2016 / 16:35