Mar*_*tin 236 java string diacritics
是否有更好的方法来摆脱重音并使这些字母与使用String.replaceAll()方法和逐个替换字母分开?例:
输入: or?pžsíáýd
输出: orcpzsiayd
它不需要包括所有带有重音符号的字母,如俄语字母或中文字母.
Eri*_*son 364
使用java.text.Normalizer来处理这个给你.
string = Normalizer.normalize(string, Normalizer.Form.NFD);
// or Normalizer.Form.NFKD for a more "compatable" deconstruction
Run Code Online (Sandbox Code Playgroud)
这会将所有重音符号与字符分开.然后,你只需要将每个角色与一个字母进行比较,然后扔掉那些不是.
string = string.replaceAll("[^\\p{ASCII}]", "");
Run Code Online (Sandbox Code Playgroud)
如果你的文字是unicode,你应该使用它:
string = string.replaceAll("\\p{M}", "");
Run Code Online (Sandbox Code Playgroud)
对于unicode,\\P{M}匹配基本字形和\\p{M}(小写)匹配每个重音.
由于GarretWilson的指针和regular-expressions.info为伟大的Unicode指南.
Dav*_*idS 121
截至2011年,您可以使用Apache Commons StringUtils.stripAccents(输入)(自3.0起):
String input = StringUtils.stripAccents("T?ï? ?š â f???? Š?????");
System.out.println(input);
// Prints "This is a funky String"
Run Code Online (Sandbox Code Playgroud)
注意:
接受的答案(Erick Robertson's)不适用于Ø或Ł.Apache Commons 3.5也不适用于Ø,但它确实适用于Ł.在阅读维基百科关于Ø的文章后,我不确定它应该替换为"O":它是挪威语和丹麦语中的单独字母,在"z"之后按字母顺序排列.这是"条带重音"方法局限性的一个很好的例子.
Dav*_*rad 51
@ virgo47的解决方案非常快,但近似.接受的答案使用Normalizer和正则表达式.我想知道Normalizer与正则表达式相比花了多少时间,因为删除所有非ASCII字符都可以在没有正则表达式的情况下完成:
import java.text.Normalizer;
public class Strip {
public static String flattenToAscii(String string) {
StringBuilder sb = new StringBuilder(string.length());
string = Normalizer.normalize(string, Normalizer.Form.NFD);
for (char c : string.toCharArray()) {
if (c <= '\u007F') sb.append(c);
}
return sb.toString();
}
}
Run Code Online (Sandbox Code Playgroud)
通过写入char []并且不调用toCharArray()可以获得小的额外加速,尽管我不确定代码清晰度的降低是否值得:
public static String flattenToAscii(String string) {
char[] out = new char[string.length()];
string = Normalizer.normalize(string, Normalizer.Form.NFD);
int j = 0;
for (int i = 0, n = string.length(); i < n; ++i) {
char c = string.charAt(i);
if (c <= '\u007F') out[j++] = c;
}
return new String(out);
}
Run Code Online (Sandbox Code Playgroud)
这种变化具有使用Normalizer的正确性以及使用表格的一些速度的正确性的优点.在我的机器上,这个比你接受的答案快4倍,比@ virgo47慢6.6倍到7倍(接受的答案比我机器上的@ virgo47慢约26倍).
vir*_*o47 28
编辑:如果你没有坚持Java <6并且速度不重要和/或翻译表太有限,请使用David的回答.关键是使用Normalizer(在Java 6中引入)而不是循环内的转换表.
虽然这不是"完美"的解决方案,但是当您知道范围(在我们的案例中为Latin1,2)时,它可以很好地工作,在Java 6之前工作(虽然不是真正的问题)并且比最建议的版本快得多(可能或可能)不是问题):
/**
* Mirror of the unicode table from 00c0 to 017f without diacritics.
*/
private static final String tab00c0 = "AAAAAAACEEEEIIII" +
"DNOOOOO\u00d7\u00d8UUUUYI\u00df" +
"aaaaaaaceeeeiiii" +
"\u00f0nooooo\u00f7\u00f8uuuuy\u00fey" +
"AaAaAaCcCcCcCcDd" +
"DdEeEeEeEeEeGgGg" +
"GgGgHhHhIiIiIiIi" +
"IiJjJjKkkLlLlLlL" +
"lLlNnNnNnnNnOoOo" +
"OoOoRrRrRrSsSsSs" +
"SsTtTtTtUuUuUuUu" +
"UuUuWwYyYZzZzZzF";
/**
* Returns string without diacritics - 7 bit approximation.
*
* @param source string to convert
* @return corresponding string without diacritics
*/
public static String removeDiacritic(String source) {
char[] vysl = new char[source.length()];
char one;
for (int i = 0; i < source.length(); i++) {
one = source.charAt(i);
if (one >= '\u00c0' && one <= '\u017f') {
one = tab00c0.charAt((int) one - '\u00c0');
}
vysl[i] = one;
}
return new String(vysl);
}
Run Code Online (Sandbox Code Playgroud)
使用32位JDK对我的硬件进行测试表明,这可以在~100ms内执行从àèéľľť89899FDČ到aeelstc89FDC的100万次转换,而Normalizer方式则在3.7s内(37x慢).如果您的需求与性能有关并且您知道输入范围,这可能适合您.
请享用 :-)
Nic*_*ico 21
System.out.println(Normalizer.normalize("àèé", Normalizer.Form.NFD).replaceAll("\\p{InCombiningDiacriticalMarks}+", ""));
Run Code Online (Sandbox Code Playgroud)
为我工作.上面代码片段的输出给出了"aee",这是我想要的,但是
System.out.println(Normalizer.normalize("àèé", Normalizer.Form.NFD).replaceAll("[^\\p{ASCII}]", ""));
Run Code Online (Sandbox Code Playgroud)
没有做任何替代.
根据语言的不同,这些可能不会被视为重音(这会改变字母的声音),而是变音符号
https://en.wikipedia.org/wiki/Diacritic#Languages_with_letters_containing_diacritics
"波斯尼亚语和克罗地亚语有符号č,ć,đ,š和ž,它们被视为单独的字母,并在字典和其他语境中按字母顺序列出.
删除它们可能会固有地改变单词的含义,或者将字母改为完全不同的字母.
| 归档时间: |
|
| 查看次数: |
127620 次 |
| 最近记录: |