Как найти целое слово в строке в Java - PullRequest
24 голосов
/ 23 февраля 2011

У меня есть строка, которую я должен проанализировать по разным ключевым словам. Например, у меня есть строка:

«Я приду и встречу тебя в 123 лесах»

И мои ключевые слова

'' 123woods 'лес'

Я должен сообщать, когда у меня есть матч и где. Многократные случаи также должны быть учтены. Однако, для этого я должен получить совпадение только на 123 лесах, а не на лесах. Это исключает использование метода String.contains (). Кроме того, я должен иметь возможность иметь список / набор ключевых слов и одновременно проверять их наличие. В этом примере, если у меня есть «123woods» и «come», я должен получить два вхождения. Выполнение метода должно быть несколько быстрым для больших текстов.

Моя идея - использовать StringTokenizer, но я не уверен, что он будет работать хорошо. Есть предложения?

Ответы [ 13 ]

38 голосов
/ 23 февраля 2011

Пример ниже основан на ваших комментариях.Он использует список ключевых слов, которые будут искать в заданной строке, используя границы слов.Он использует StringUtils из Apache Commons Lang для построения регулярного выражения и печати совпадающих групп.

String text = "I will come and meet you at the woods 123woods and all the woods";

List<String> tokens = new ArrayList<String>();
tokens.add("123woods");
tokens.add("woods");

String patternString = "\\b(" + StringUtils.join(tokens, "|") + ")\\b";
Pattern pattern = Pattern.compile(patternString);
Matcher matcher = pattern.matcher(text);

while (matcher.find()) {
    System.out.println(matcher.group(1));
}

Если вам нужна дополнительная производительность, вы можете взглянуть на StringSearch : highалгоритмы сопоставления с образцом в Java.

14 голосов
/ 23 февраля 2011

Используйте регулярные выражения + границы слов, как ответили другие.

"I will come and meet you at the 123woods".matches(".*\\b123woods\\b.*");

будет правдой.

"I will come and meet you at the 123woods".matches(".*\\bwoods\\b.*");

будет ложным.

10 голосов
/ 23 февраля 2011

Надеюсь, что это работает для вас:

String string = "I will come and meet you at the 123woods";
String keyword = "123woods";

Boolean found = Arrays.asList(string.split(" ")).contains(keyword);
if(found){
      System.out.println("Keyword matched the string");
}

http://codigounico.blogspot.com/

9 голосов
/ 23 февраля 2011

Как насчет чего-то вроде Arrays.asList(String.split(" ")).contains("xx")?

См. String.split () и Как проверить, содержит ли массив определенное значение .

3 голосов
/ 07 июля 2015

Получил путь к совпадению Точное слово из Строка в Android:

String full = "Hello World. How are you ?";

String one = "Hell";
String two = "Hello";
String three = "are";
String four = "ar";


boolean is1 = isContainExactWord(full, one);
boolean is2 = isContainExactWord(full, two);
boolean is3 = isContainExactWord(full, three);
boolean is4 = isContainExactWord(full, four);

Log.i("Contains Result", is1+"-"+is2+"-"+is3+"-"+is4);

Result: false-true-true-false

Функция для слова соответствия:

private boolean isContainExactWord(String fullString, String partWord){
    String pattern = "\\b"+partWord+"\\b";
    Pattern p=Pattern.compile(pattern);
    Matcher m=p.matcher(fullString);
    return m.find();
}

Выполнено

2 голосов
/ 23 февраля 2011

Попробуйте сопоставить с помощью регулярных выражений.Соответствует "\ b123wood \ b", \ b - разрыв слова.

1 голос
/ 13 августа 2016

Решение, кажется, давно принято, но решение может быть улучшено, поэтому, если у кого-то есть подобная проблема:

Это классическое приложение для алгоритмов поиска по нескольким шаблонам.

Поиск по шаблону Java (с Matcher.find) не подходит для этого.Поиск точно по одному ключевому слову оптимизирован в Java, при поиске выражения or используется недетерминированный автомат регулярных выражений, который отслеживает несоответствия.В худшем случае каждый символ текста будет обработан l раз (где l - сумма длин шаблона).

Поиск по одному шаблону лучше, но также не квалифицирован.Нужно начинать весь поиск по каждому шаблону ключевых слов.В худшем случае каждый символ текста будет обработан p раз, где p - количество шаблонов.

При поиске по нескольким шаблонам каждый символ текста обрабатывается ровно один раз.Алгоритмы, подходящие для такого поиска, будут Aho-Corasick, Wu-Manber или Set Backwards Oracle Matching.Их можно найти в таких библиотеках, как Stringsearchalgorithms или byteseek .

// example with StringSearchAlgorithms

AhoCorasick stringSearch = new AhoCorasick(asList("123woods", "woods"));

CharProvider text = new StringCharProvider("I will come and meet you at the woods 123woods and all the woods", 0);

StringFinder finder = stringSearch.createFinder(text);

List<StringMatch> all = finder.findAll();
1 голос
/ 11 октября 2012

Более простой способ сделать это - использовать split ():

String match = "123woods";
String text = "I will come and meet you at the 123woods";

String[] sentence = text.split();
for(String word: sentence)
{
    if(word.equals(match))
        return true;
}
return false;

Это более простой и менее элегантный способ сделать то же самое без использования токенов и т. Д.

0 голосов
/ 21 июня 2018
public class FindTextInLine {
    String match = "123woods";
    String text = "I will come and meet you at the 123woods";

    public void findText () {
        if (text.contains(match)) {
            System.out.println("Keyword matched the string" );
        }
    }
}
0 голосов
/ 14 июля 2015

Оглядываясь на исходный вопрос, нам нужно найти несколько заданных ключевых слов в данном предложении, посчитать количество вхождений и кое-что узнать о том, где.Я не совсем понимаю, что означает "где" (это индекс в предложении?), Поэтому я пропущу этот ... Я все еще изучаю Java, один шаг за раз, поэтому я посмотрюк этому в свое время: -)

Следует отметить, что общие предложения (как и в исходном вопросе) могут иметь повторяющиеся ключевые слова, поэтому поиск не может просто спросить, существует ли данное ключевое слово "или нет"и считать его как 1, если он существует.Там может быть более одного того же.Например:

// Base sentence (added punctuation, to make it more interesting):
String sentence = "Say that 123 of us will come by and meet you, "
                + "say, at the woods of 123woods.";

// Split it (punctuation taken in consideration, as well):
java.util.List<String> strings = 
                       java.util.Arrays.asList(sentence.split(" |,|\\."));

// My keywords:
java.util.ArrayList<String> keywords = new java.util.ArrayList<>();
keywords.add("123woods");
keywords.add("come");
keywords.add("you");
keywords.add("say");

Глядя на это, ожидаемый результат будет 5 для "Скажи" + "приходи" + "ты" + "говори" + "123 леса", считая "скажи" дважды, еслимы идем в нижнем регистре.Если мы этого не сделаем, то число должно быть 4, исключая «Скажи» и включая «Скажи».Хорошо.Мое предложение:

// Set... ready...?
int counter = 0;

// Go!
for(String s : strings)
{
    // Asking if the sentence exists in the keywords, not the other
    // around, to find repeated keywords in the sentence.
    Boolean found = keywords.contains(s.toLowerCase());
    if(found)
    {
        counter ++;
        System.out.println("Found: " + s);
    }
}

// Statistics:
if (counter > 0)
{
    System.out.println("In sentence: " + sentence + "\n"
                     + "Count: " + counter);
}

И результаты:

Найдено: Сказать
Найдено: прийти
Найдено: вы
Найдено: сказать
Найдено: 123 леса
В предложении: Скажите, что 123 из нас придут и встретят вас, скажем, в лесах 123 леса.
Количество: 5

...