2011-01-22 11 views
6

Digamos que tengo esta lista de palabras:cadenas eliminar de otra cadena en Java

String[] stopWords = new String[]{"i","a","and","about","an","are","as","at","be","by","com","for","from","how","in","is","it","not","of","on","or","that","the","this","to","was","what","when","where","who","will","with","the","www"}; 

que he texto

String text = "I would like to do a nice novel about nature AND people" 

¿Hay un método que coincide con las palabras vacías y los elimina sin tener en cuenta el caso ; como este en algún lugar ?:

String noStopWordsText = remove(text, stopWords); 

Resultado:

" would like do nice novel nature people" 

Si usted sabe acerca de expresiones regulares que wold funcionan muy bien, pero yo realmente preferiría algo así como solución de los Comunes que es poco más orientada hacia el rendimiento.

Por cierto, en este momento estoy usando este método bienes comunes que le falta el manejo adecuado entre mayúsculas y minúsculas:

private static final String[] stopWords = new String[]{"i", "a", "and", "about", "an", "are", "as", "at", "be", "by", "com", "for", "from", "how", "in", "is", "it", "not", "of", "on", "or", "that", "the", "this", "to", "was", "what", "when", "where", "who", "will", "with", "the", "www", "I", "A", "AND", "ABOUT", "AN", "ARE", "AS", "AT", "BE", "BY", "COM", "FOR", "FROM", "HOW", "IN", "IS", "IT", "NOT", "OF", "ON", "OR", "THAT", "THE", "THIS", "TO", "WAS", "WHAT", "WHEN", "WHERE", "WHO", "WILL", "WITH", "THE", "WWW"}; 
private static final String[] blanksForStopWords = new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}; 

noStopWordsText = StringUtils.replaceEach(text, stopWords, blanksForStopWords);  
+0

¿Tiene puntuación en sus cadenas? – Gabe

+0

¿Tiene algunos números duros que apuntan a que una solución de expresiones regulares no es lo suficientemente eficiente, o es solo una optimización prematura? Es decir, definitivamente no es la solución más eficiente, pero a menos que esto sea todo lo que haga y necesite hacerlo 10 mil veces por segundo, apostaría a que no es un problema. – Theo

Respuesta

4

Esta es una solución que no usa expresiones regulares. Creo que es inferior a mi otra respuesta porque es mucho más larga y menos clara, pero si el rendimiento es realmente importante, entonces esto es O (n) donde n es la longitud del texto.

Set<String> stopWords = new HashSet<String>(); 
stopWords.add("a"); 
stopWords.add("and"); 
// and so on ... 

String sampleText = "I would like to do a nice novel about nature AND people"; 
StringBuffer clean = new StringBuffer(); 
int index = 0; 

while (index < sampleText.length) { 
    // the only word delimiter supported is space, if you want other 
    // delimiters you have to do a series of indexOf calls and see which 
    // one gives the smallest index, or use regex 
    int nextIndex = sampleText.indexOf(" ", index); 
    if (nextIndex == -1) { 
    nextIndex = sampleText.length - 1; 
    } 
    String word = sampleText.substring(index, nextIndex); 
    if (!stopWords.contains(word.toLowerCase())) { 
    clean.append(word); 
    if (nextIndex < sampleText.length) { 
     // this adds the word delimiter, e.g. the following space 
     clean.append(sampleText.substring(nextIndex, nextIndex + 1)); 
    } 
    } 
    index = nextIndex + 1; 
} 

System.out.println("Stop words removed: " + clean.toString()); 
+0

Muy cierto, cambié el 'break' en' nextIndex = sampleText.length', que debería resolver eso. – Theo

+0

Ooops, eso es realmente lo que probé, pero estaba descuidado cuando cambié el código. Gracias por señalar eso. – Theo

5

se puede hacer una expresión reg para que coincida todo lo alto palabras [por ejemplo a, nota espacio aquí] y terminar con

str.replaceAll(regexpression,""); 

O

String[] stopWords = new String[]{" i ", " a ", " and ", " about ", " an ", " are ", " as ", " at ", " be ", " by ", " com ", " for ", " from ", " how ", " in ", " is ", " it ", " not ", " of ", " on ", " or ", " that ", " the ", " this ", " to ", " was ", " what ", " when ", " where ", " who ", " will ", " with ", " the ", " www "}; 
     String text = " I would like to do a nice novel about nature AND people "; 

     for (String stopword : stopWords) { 
      text = text.replaceAll("(?i)"+stopword, " "); 
     } 
     System.out.println(text); 

de salida:

would like do nice novel nature people 

No podría ser mejor manera.

+0

1) No cumple con el requisito de que el método sea insensible a mayúsculas y minúsculas. 2) no elimina stop _words_ - eliminaría "no" en "novela". – Theo

+0

@Theo check update –

+0

Truco inteligente, no sabía que era posible. La única crítica que tengo es que 'replaceAll' es realmente ineficiente, compila un patrón de expresiones regulares único, así que usarlo en un bucle no es genial. – Theo

16

Crear una expresión regular con sus palabras vacías, que sea sensible a mayúsculas, y luego usar el método de la matcher replaceAll para reemplazar todos los partidos con una cadena vacía

import java.util.regex.*; 

Pattern stopWords = Pattern.compile("\\b(?:i|a|and|about|an|are|...)\\b\\s*", Pattern.CASE_INSENSITIVE); 
Matcher matcher = stopWords.matcher("I would like to do a nice novel about nature AND people"); 
String clean = matcher.replaceAll(""); 

la ... en el patrón es sólo yo ser perezoso , continúa la lista de palabras de finalización.

Otro método es recorrer todas las palabras de finalización y usar el método StringreplaceAll. El problema con este enfoque es que replaceAll compilará una nueva expresión regular para cada llamada, por lo que no es muy eficiente utilizar los bucles. Además, no puede pasar la bandera que hace que la expresión regular no sea sensible cuando usa StringreplaceAll.

Editar: He añadido \b alrededor del patrón para que coincida con palabras completas solamente. También agregué \s* para hacer que ocupe todos los espacios después, quizás no sea necesario.

+0

[¿Funcionará el código?] (Http://ideone.com/F7m9f) –

+0

Sí, debería. Tuve un error en la expresión regular, \ b necesita ser \\ b en Java, lo olvidé. Pero ahora debería funcionar. – Theo

+0

Ok. quiero +1 pero mi voto ya está bloqueado. –

1

Split text en whilespace. A continuación, recorra el conjunto y continúe añadiendo a StringBuilder solo si no es una de las palabras de finalización.

Cuestiones relacionadas