У меня есть список фраз (фраза может состоять из одного или нескольких слов) в базе данных и входная строка. Мне нужно выяснить, какие из этих фраз появляются во входной строке.
Есть ли эффективный способ выполнить такое сопоставление в Java?
У меня есть список фраз (фраза может состоять из одного или нескольких слов) в базе данных и входная строка. Мне нужно выяснить, какие из этих фраз появляются во входной строке.
Есть ли эффективный способ выполнить такое сопоставление в Java?
Быстрый взлом будет:
find
до тех пор, пока не будут найдены все фразы или не будет достигнут конец ввода, удаляя совпадения из набора оставшихся фраз для поиска.Таким образом, вход проходит только один раз, независимо от того, сколько фраз вы вводите. Если компилятор регулярных выражений генерирует эффективный сопоставитель для нескольких альтернатив, это должно обеспечить достойную производительность. Однако это во многом зависит от ваших фраз и входной строки, а также от качества механизма регулярных выражений Java.
Пример кода (протестирован, но не оптимизирован и не профилирован для производительности):
public static boolean hasAllPhrasesInInput(List<String> phrases, String input) {
Set<String> phrasesToFind = new HashSet<String>();
StringBuilder sb = new StringBuilder();
for (String phrase : phrases) {
if (sb.length() > 0) {
sb.append('|');
}
sb.append(Pattern.quote(phrase));
phrasesToFind.add(phrase.toLowerCase());
}
Pattern pattern = Pattern.compile(sb.toString(), Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(input);
while (matcher.find()) {
phrasesToFind.remove(matcher.group().toLowerCase());
if (phrasesToFind.isEmpty()) {
return true;
}
}
return false;
}
Некоторые предостережения:
Pattern.UNICODE_CASE
и вызвать toLowerCase(Locale)
вместо toLowerCase()
, используя подходящий Locale
.Вот решение с использованием java. Поскольку вы ничего не указали о строках, которые вы используете, я рассматриваю общий пример
Pattern p = Pattern.compile("cat");
// Create a matcher with an input string
Matcher m = p.matcher("one cat," +" two cats in the yard");
boolean b = m.matches(); // Should return true
надеюсь, это поможет
Ссылка: http://java.sun.com/developer/technicalArticles/releases/1.4regex/
Вы можете организовать поисковые фразы из вашей базы данных в дерево на основе общего начала. Затем вы можете анализировать символ строки за символом, пытаясь сопоставить его с узлами этого дерева.
sql = "SELECT phrase " +
" FROM phrases " +
" WHERE phrase LIKE $1";
PreparedStatement pstmt = conn.prepareStatement (sql);
// probably repeated, if more than one input:
pstmt.setString (1, "%" + input + "%");
ResultSet rs = pstmt.executeQuery ();
Подготовленный оператор проверяется на соответствие базе данных и быстрее для повторного вызова, поэтому, если у вас есть более одного ввода, он все равно должен быть быстрым, выполняемым в цикле.
Конечно, вы могли загрузить все свои фразы в оперативную память, на карту. Медленная подготовка, может быть быстрее, если у вас есть несколько вызовов, а не только один ввод. Но базы данных часто весьма эффективны для поиска.