2012-01-05 10 views
11

Tengo que probar si una cadena está incluida en otra pero sin considerar el caso o acentos (acentos franceses en este caso). Por ejemplo, la función debe devolver true si busco "rhone" en la cadena "Vallée du Rhône".contiene con el clasificador

El intercalador es útil para la comparación de cadenas con acentos, pero no proporciona una función contains.

¿Hay una manera fácil de hacer el trabajo? Un regex tal vez?

Información adicional:
sólo necesito un valor de retorno true/false, no me importa sobre el número de partidos o la posición de la cadena de prueba en la cadena de referencia.

+0

Desafortunadamente, java.util.regex no admite secuencias de clasificación, de lo contrario se podría haber hecho probado y partido contra '\ brh [[= o =]] ne \ b' ... – fge

Respuesta

16

Puede usar Normalizer para reducir cadenas a versiones reducidas que puede comparar directamente.

Editar: para ser claro

String normalized = Normalizer.normalize(text, Normalizer.Form.NFD); 
String ascii = normalized.replaceAll("[^\\p{ASCII}]", ""); 
0

La forma normal de hacer esto es convertir las dos cadenas en minúsculas y sin acentos, y luego usar el estándar 'contiene'.

10

Eche un vistazo a Normalizer.

Debería llamarlo con Normalizer.Form.NFD como segundo argumento.

Por lo tanto, sería:

Normalizer.normalize(yourinput, Normalizer.Form.NFD) 
    .replaceAll("\\p{InCombiningDiacriticalMarks}+", "") 
    .toLowerCase() 
    .contains(yoursearchstring) 

que devolverá verdadero si partido (y, por supuesto, falso en caso contrario)

+1

No Será este descomponer 'è' en 'e' '? Eso haría que contain() falla a menos que los caracteres acentuados sean siempre los últimos de la cadena. – Viruzzo

+0

¡Uy! Correcto. Fijo. – fge

3

¿Qué tal esto?

private static final Pattern ACCENTS_PATTERN = Pattern.compile("\\p{InCombiningDiacriticalMarks}+"); 

public static boolean containsIgnoreCaseAndAccents(String haystack, String needle) { 
    final String hsToCompare = removeAccents(haystack).toLowerCase(); 
    final String nToCompare = removeAccents(needle).toLowerCase(); 

    return hsToCompare.contains(nToCompare); 
} 

public static String removeAccents(String string) { 
    return ACCENTS_PATTERN.matcher(Normalizer.normalize(string, Normalizer.Form.NFD)).replaceAll(""); 
} 

public static void main(String[] args) { 
    System.out.println(removeAccents("Vallée du Rhône")); 
    System.out.println(removeAccents("rhone")); 
    System.out.println(containsIgnoreCaseAndAccents("Vallée du Rhône", "rhone")); 

} 
Cuestiones relacionadas