saber - Usando Java Regex, ¿cómo verificar si una cadena contiene alguna de las palabras en un conjunto?
saber si una cadena contiene espacios java (3)
Tengo un conjunto de palabras como: manzana, naranja, pera, plátano, kiwi
Quiero verificar si una oración contiene alguna de las palabras enumeradas anteriormente, y si lo hace, quiero encontrar qué palabra coincide. ¿Cómo puedo lograr esto en Regex?
Actualmente estoy llamando a String.indexOf () para cada uno de mis conjuntos de palabras. ¿Asumo que esto no es tan eficiente como una coincidencia de expresiones regulares?
TL; DR Para subcadenas simples
contains()
es mejor, pero para solo emparejar palabras completas, la expresión regular es probablemente mejor.
La mejor manera de ver qué método es más eficiente es probarlo.
Puede usar String.contains()
lugar de String.indexOf()
para simplificar su código no regexp.
Para buscar diferentes palabras, la expresión regular se ve así:
apple|orange|pear|banana|kiwi
El |
funciona como un OR
en expresiones regulares.
Mi código de prueba muy simple se ve así:
public class TestContains {
private static String containsWord(Set<String> words,String sentence) {
for (String word : words) {
if (sentence.contains(word)) {
return word;
}
}
return null;
}
private static String matchesPattern(Pattern p,String sentence) {
Matcher m = p.matcher(sentence);
if (m.find()) {
return m.group();
}
return null;
}
public static void main(String[] args) {
Set<String> words = new HashSet<String>();
words.add("apple");
words.add("orange");
words.add("pear");
words.add("banana");
words.add("kiwi");
Pattern p = Pattern.compile("apple|orange|pear|banana|kiwi");
String noMatch = "The quick brown fox jumps over the lazy dog.";
String startMatch = "An apple is nice";
String endMatch = "This is a longer sentence with the match for our fruit at the end: kiwi";
long start = System.currentTimeMillis();
int iterations = 10000000;
for (int i = 0; i < iterations; i++) {
containsWord(words, noMatch);
containsWord(words, startMatch);
containsWord(words, endMatch);
}
System.out.println("Contains took " + (System.currentTimeMillis() - start) + "ms");
start = System.currentTimeMillis();
for (int i = 0; i < iterations; i++) {
matchesPattern(p,noMatch);
matchesPattern(p,startMatch);
matchesPattern(p,endMatch);
}
System.out.println("Regular Expression took " + (System.currentTimeMillis() - start) + "ms");
}
}
Los resultados que obtuve fueron los siguientes:
Contains took 5962ms
Regular Expression took 63475ms
Obviamente, los tiempos variarán dependiendo del número de palabras que se buscan y las cadenas que se buscan, pero contains()
parece ser ~ 10 veces más rápido que las expresiones regulares para una búsqueda simple como esta.
Al usar Expresiones regulares para buscar Cadenas dentro de otra Cadena, estás usando una maza para romper una nuez, así que supongo que no debería sorprendernos que sea más lenta. Guarde expresiones regulares para cuando los patrones que desea encontrar son más complejos.
Un caso en el que desee utilizar Expresiones regulares es si indexOf()
y contains()
no harán el trabajo porque solo desea hacer coincidir palabras completas y no solo subseries, por ejemplo, si desea hacer coincidir pear
pero no spears
. Las expresiones regulares manejan bien este caso ya que tienen el concepto de límites de palabras .
En este caso, cambiaríamos nuestro patrón a:
/b(apple|orange|pear|banana|kiwi)/b
El /b
dice que solo coincide con el comienzo o el final de una palabra y los corchetes agrupan las expresiones OR juntas.
Tenga en cuenta que, al definir este patrón en su código, debe escapar de las barras invertidas con otra barra invertida:
Pattern p = Pattern.compile("//b(apple|orange|pear|banana|kiwi)//b");
Aquí está la solución más simple que encontré (haciendo coincidir con comodines):
boolean a = str.matches(".*//b(wordA|wordB|wordC|wordD|wordE)//b.*");
No creo que una expresión regular haga un mejor trabajo en términos de rendimiento, pero puedes usarla de la siguiente manera:
Pattern p = Pattern.compile("(apple|orange|pear)");
Matcher m = p.matcher(inputString);
while (m.find()) {
String matched = m.group(1);
// Do something
}