Как отфильтровать текст, чтобы учесть пробелы?

Я создаю окно поиска для своего приложения, где пользователь может вводить данные в поле, а заголовки возвращаются в recyclerView под полем поиска. Заголовки находятся в файле php на сервере - результаты фильтруются в соответствии с тем, что пользователь вводит в поле поиска.

Так, например, одно из заголовков в моем файле php:

red onions

Если пользователь набирает red, recyclerView показывает, как он набирает:

red cabbage
red mushrooms
red onions

Эта часть работает правильно.

Но когда пользователь набирает red o, в recyclerView ничего не отображается. Тогда как, собственно, должен появиться red onions.

Я уверен, что это происходит, потому что в моем приложении я разбиваю заголовки php на отдельные слова, поэтому пробел (" ") между red и onions вызывает проблему.

Есть идеи, как я могу это восстановить?

Причина, по которой я разбиваю заголовок на слова в первую очередь, заключается в том, что если пользователь вводит второе слово, onions, red onions будет отображаться в результате в recyclerView, а не вообще ничего.

Вот мой код:

      @Override
            public Filter getFilter() {
                return new Filter() {
                    @Override
                    protected FilterResults performFiltering(CharSequence charSequence) {

                        //the text entered in the search box
                        String charString = charSequence.toString();

                        //if searchbox is empty, show the whole list
                        if (charString.isEmpty()) {
                            categoryListFiltered = categoryList;
                        } else {
                            List<Category> filteredList = new ArrayList<>();

                            for (Category row : categoryList) {

                                //split the php title into separate words
                                String[] title_in_php = row.getName().split(" ");

                                //for every split word
                                for (String split_title : title_in_php) {

//if the search term entered is a whole word in the title
                        if (split_title.toLowerCase().startsWith(charString.toLowerCase())) { 

                                        filteredList.add(row);

                                    }
                                }
                            }

                            categoryListFiltered = filteredList;
                        }

                        FilterResults filterResults = new FilterResults();

                        filterResults.values = categoryListFiltered;
                        return filterResults;
                    }

                    @Override
                    protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
                        categoryListFiltered = (ArrayList<Category>) filterResults.values;
                        notifyDataSetChanged();
                    }
                };
            }

Код разбивается на " ", который не включен в String []. Попробуйте row.getName().startsWith(charString);

Andrew S 27.03.2018 17:59

спасибо, но если я это сделаю, то в представлении ресайклера будут отображаться только заголовки, начинающиеся с поискового запроса. Если пользователь набирает «лук», ничего не отображается.

CHarris 27.03.2018 18:04

Тогда попробуйте row.getName().contains(charString).

Andrew S 27.03.2018 18:06

Предполагая, что «красный лук» эквивалентен «красный лук», вам также придется разделить введенную строку charString и объединить поиск с помощью AND.

Andy 27.03.2018 18:11

@AndrewS При этом, если поисковый запрос находится в любой части заголовка, результаты появляются в recyclerView. Например, «ion» возвращает «лук». Ищем только слова целиком.

CHarris 27.03.2018 18:11

что, если пользователь набирает «лук-лук»?

Andrew S 27.03.2018 18:21

С "луком-луком" ничего не будет отображаться, и это правильно, потому что в базе данных нет заголовка с таким названием.

CHarris 27.03.2018 19:17

Может быть проще, если вы разместите более полные тестовые данные и ожидаемый результат.

Andy 27.03.2018 19:20
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
8
79
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

После того, как вы ввели red o, он сначала проверит red и добавит row в filterList, потому что charString начинается с red, но проверка o не добавит row в filterList, потому что charString не начинается с o.

Попробуйте это (на основе комментариев):

if (split_title.toLowerCase().startsWith(charString.toLowerCase())) {
    filteredList.add(row);
}
else if (row.getName().contains(charString.toLowerCase()) {
    if (!filteredList.contains(row)) {
        filteredList.add(row);
    }
}

if для проверки split_title (например, red) - filterList.add (row);

else if проверит, содержит ли rowcharString (целая строка, например, red o) - filterList.add (строка);

if (!filteredList.contains(row)) просто проверяет, есть ли строка в списке. Если нет, то добавьте его. (Чтобы избежать дублирования)

Другой способ - разделить charString:

String[] charString= charSequence.toString().split(" ")

и повторить его:

for (int i=0; i<charString.length; i++) {
    for (int n=0; n<title_in_php.length; n++) {
        if (split_title.toLowerCase().startsWith(charString.toLowerCase()) || charString[i].toLowerCase() == title_in_php[n].toLowerCase() || row.getName().contains(charString.toLowerCase()) {
            if (!filteredList.contains(row)) {
                filteredList.add(row);
            }
        }
    }
}

поэтому он проверит, начинается ли charString с title_in_phpИЛИ ЖЕ, если charString = title_in_phpИЛИ ЖЕ, если row содержит charString, проверяя список title_in_php на charString

[красный] начинается с [красный лук]ИЛИ ЖЕ[красный] = [красный лук]ИЛИ ЖЕ[красный лук] содержит [красный o]

Отличная, приятная работа. Я внес несколько небольших изменений, которые вскоре добавлю к вашему ответу выше, но в целом это решило проблему, tx.

CHarris 28.03.2018 11:44

Другие вопросы по теме