2011-02-23 25 views
22

Tengo una cadena que tengo que analizar para diferentes palabras clave. Por ejemplo, tengo el encordado:Cómo encontrar una palabra completa en una cadena en java

"Vendré y que se reúnen en las 123woods"

Y mis palabras clave son

que deberían informar '123woods' 'bosques' cada vez que tengo un partido y dónde. Múltiples ocurrencias también deben ser contabilizadas. Sin embargo, para este, debería conseguir un partido solo en 123woods, no en bosques. Esto elimina el uso del método String.contains(). Además, debería poder tener una lista/conjunto de palabras clave y verificar al mismo tiempo su ocurrencia. En este ejemplo, si tengo '123woods' y 'come', debería obtener dos apariciones. La ejecución del método debe ser algo rápida en textos grandes.

Mi idea es utilizar StringTokenizer pero no estoy seguro si funcionará bien. ¿Alguna sugerencia?

+1

¿Estás seguro de que la lógica no es defectuosa? Qué sucede si tiene palabras clave - palabras123 y 123 palabras. ¿Entonces en el texto palabras123 palabras que son las coincidencias? –

+0

Ninguno. Solo necesito coincidencias exactas de palabras. –

Respuesta

33

El ejemplo siguiente se basa en sus comentarios. Utiliza una lista de palabras clave, que se buscará en una cadena determinada utilizando límites de palabras. Utiliza StringUtils de Apache Commons Lang para construir la expresión regular e imprimir los grupos coincidentes.

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)); 
} 

Si usted está buscando más el rendimiento, se puede echar un vistazo a StringSearch: Modelo de alto rendimiento de algoritmos de correspondencia en Java.

+0

¿Qué sucede si tengo un ArrayList y quiero usar un patrón para compilarlo? Parece que tengo que usar el viejo y confiable StringBuilder? –

+1

@baba - Podría hacer eso, o podría recorrer la Lista <>. No estoy seguro de cuál sería más eficiente, es posible que desee probar ambos enfoques si el rendimiento es una preocupación. –

+0

Personalmente, preferiría repetir la lista. Agregué esta opción a mi respuesta. – Chris

0

Puede usar expresiones regulares. Utilice los métodos de Matcher y Patrón para obtener la salida deseada

0

También puede usar la coincidencia de expresiones regulares con el indicador \ b (límite de palabras completas).

2

Intenta hacer coincidir el uso de expresiones regulares. Coincide con "\ b123wood \ b", \ b es un salto de palabra.

12

Usa los límites de palabras de regex + como otros respondieron.

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

será cierto.

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

serán falsos.

8

Espero que esto funcione para usted:

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/

0

Una manera mucho más sencilla de hacer esto es utilizar 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; 

Se trata de un simple, menos elegante forma de hacer lo mismo sin usar tokens, etc.

+0

Aunque es más fácil de entender y escribir, no es la respuesta a la pregunta que estaba formulando. Tengo dos o tres, o quizás una cantidad indefinida de palabras clave de "coincidencia", necesito obtener las que se encontraron en el "texto". Por supuesto, puede buclear mis palabras clave de "coincidencia" para cada una de las "palabras" en el texto dividido, pero me parece mucho menos elegante que la solución ya aceptada. –

0

Para que coincida con "123woods" de "maderas", usa la agrupación atómica en la expresión regular. Una cosa que debe tenerse en cuenta es que, en una cadena para que coincida con "123woods" solo, coincidirá con el primer "123woods" y se cierra en lugar de buscar la misma cadena más.

\b(?>123woods|woods)\b 

busca 123woods como búsqueda principal, una vez que ha coincidido, sale de la búsqueda.

2

tiene una manera de partidopalabra exacta de cadena en 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 

función de coincidencia de palabras:

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(); 
} 

Hecho

0

Mirando hacia atrás a la pregunta original, necesitamos encontrar algunas palabras clave en una oración dada, contar el número de ocurrencias y saber algo sobre dónde. No entiendo muy bien qué significa "dónde" (¿es un índice en la oración?), Así que pasaré ese ... Todavía estoy aprendiendo Java, un paso a la vez, así que veré a ese a su debido tiempo :-)

Debe tenerse en cuenta que las oraciones comunes (como la de la pregunta original) pueden tener palabras clave repetidas, por lo tanto la búsqueda no puede simplemente preguntar si una palabra clave determinada "existe o no" y cuente como 1 si existe. Puede haber más de uno de lo mismo. Por ejemplo:

// 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"); 

Por mirarlo, el resultado esperado sería 5 para "decir" + "ven" + "usted" + "di" + "123woods", contando "decir" dos veces si vamos minúsculas Si no lo hacemos, entonces el conteo debe ser 4, "Say" es excluido y "say" incluido. Multa. Mi sugerencia es:

// 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); 
} 

y los resultados son:

Encontrado: Di
Encontrado: llegado
Encontrado: que
Encontrado: decir
encontrados: 123woods
En la oración: SAY que 123 de nosotros vendremos y te encontraremos, digamos, en el bosque de 123woods.
Contador de visitas: 5

0

La solución parece estar aceptado desde hace tiempo, pero la solución podría ser mejorado, así que si alguien tiene un problema similar:

Esta es una aplicación clásica de multi-patrón-Buscar- algoritmos.

Búsqueda de patrón de Java (con Matcher.find) no está calificado para hacer eso. La búsqueda de exactamente una palabra clave está optimizada en Java, la búsqueda de una expresión-o utiliza el autómata no determinista regex, que está retrocediendo en desajustes. En el peor de los casos, cada carácter del texto se procesará l veces (donde l es la suma de las longitudes del patrón).

La búsqueda de un solo patrón es mejor, pero no calificada, también. Uno tendrá que comenzar la búsqueda completa de cada patrón de palabra clave. En el peor de los casos, cada carácter del texto se procesará p veces, donde p es el número de patrones.

La búsqueda de patrón múltiple procesará cada carácter del texto exactamente una vez. Los algoritmos adecuados para dicha búsqueda serían Aho-Corasick, Wu-Manber o Set Backwards Oracle Matching. Se pueden encontrar en bibliotecas como Stringsearchalgorithms o 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(); 
Cuestiones relacionadas