Проверить, находится ли подстрока в строке, игнорируя прописные, строчные и специальные символы? - PullRequest
0 голосов
/ 29 февраля 2020

Я пытаюсь проверить, есть ли фраза типа "Домашняя пицца!" содержит строку типа «пицца», НО я хочу, чтобы она всегда была истинной, не имеет значения, пицца это или пицца, или пицца! или пицца!

Я объясню код:

recipesFounded - это массив, содержащий заголовок, описание и т. д. c. Вот почему я ставлю recipesFounded.get(i).getTitle().

Проблема в том, что у меня есть "Домашняя пицца!" Строка, так что если я ищу "Пицца!" это хорошо, потому что рецепт добавлен в новый список рецептов trueOnes, но если я буду искать пиццу (без Mayus P и!), это не так.

Слово - это строка, которую я хочу найти ( pizza, Pizza! ... )


for (int i=0; i < recipesFounded.size(); i++) {
    if (recipesFounded.get(i).getTitle().contains(word)) {
       trueOnes.add(recipesFounded.get(i));
    }
}

Ответы [ 2 ]

3 голосов
/ 29 февраля 2020

Используйте метод toLowerCase из String


word = word.replaceAll("[^a-zA-Z]","").toLowerCase(); // keep only letters

За Андреас предложение, преобразуйте слово в нижний регистр перед циклом. Это более эффективно.

for (int i=0; i < recipesFounded.size(); i++) {
    if (recipesFounded.get(i).getTitle().toLowerCase()
              .contains(word)) {
       trueOnes.add(recipesFounded.get(i));
    }
}

Поскольку List реализует интерфейс iterable, вы можете сделать это следующим образом. Предполагается, что вы используете класс с именем Recipe

for (Recipe recipe : recipesFounded) {
    if (recipe.getTitle().toLowerCase()
            .contains(word)) {
       trueOnes.add(recipe);
    }
}
2 голосов
/ 29 февраля 2020

Для поиска букв / цифр в указанном порядке, игнорируя прописные и строчные буквы, пробелы и специальные символы, лучше всего преобразовать строку поиска в регулярное выражение .

Чтобы строка поиска "foobar" соответствовала "Foo-Bar", нам нужно разрешить специальные символы между любыми буквенными символами c символов.

Для полной поддержки Unicode мы будем использовать \p{Alnum} и флаги UNICODE_CHARACTER_CLASS, CASE_INSENSITIVE и UNICODE_CASE или, скорее, заглавные буквы P для не алфавита.

Чтобы сопоставить, например, A с Á, мы также разлагаем символы Юникода, используя Normalizer.normalize(str, Normalizer.Form.NFD).

Вот Пример того, как это сделать:

static List<String> search(List<String> texts, String word) {
    String regex = Normalizer.normalize(word, Normalizer.Form.NFD) // e.g. "Á"  ->  "A\u0301"
            .replaceAll("(?U)\\P{Alnum}+", "")                     // e.g. "I'm!"  ->  "Im"
            .replaceAll("(?<=.)(?=.)", "\\\\P{Alnum}*"); // insert '\\P{Alnum}*' between all characters 
    Pattern p = Pattern.compile(regex, Pattern.UNICODE_CHARACTER_CLASS |
                                       Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
    List<String> trueOnes = new ArrayList<>();
    for (String text : texts) {
        if (p.matcher(Normalizer.normalize(text, Normalizer.Form.NFD)).find()) {
            trueOnes.add(text);
        }
    }
    return trueOnes;
}

Тесты

List<String> texts = List.of("Homemade Pizza!", "Dessert", "Pizza Hut", "Potato-Söûp", "O'Malleys Ale");
System.out.println(search(texts, "pizza"));    // [Homemade Pizza!, Pizza Hut]
System.out.println(search(texts, "made, pi")); // [Homemade Pizza!]
System.out.println(search(texts, "ömÁl"));     // [O'Malleys Ale]
System.out.println(search(texts, "TOSO"));     // [Potato-Söûp]
...