분음 부호 ( 틸드 , 곡절 , 캐럿 , 움라우트 , 카론 )와 “단순”문자 사이를 매핑 할 수있는 알고리즘을 찾고 있습니다 .
예를 들면 :
ń ǹ ň ñ ṅ ņ ṇ ṋ ṉ ̈ ɲ ƞ ᶇ ɳ ȵ --> n
á --> a
ä --> a
ấ --> a
ṏ --> o
기타.
-
나는 이것이 유니 코드 형식이어야하고 어떤 언어로도 합리적으로 쉽게 할 수 있어야한다고 생각하지만 자바로 이것을하고 싶다.
-
목적 : 분음 부호가있는 단어를 쉽게 검색 할 수 있습니다. 예를 들어, 테니스 선수 데이터베이스가 있고 Björn_Borg가 입력 된 경우 Bjorn_Borg도 유지하므로 Björn이 아닌 누군가가 Bjorn에 입력하면 찾을 수 있습니다.
답변
최근 Java에서이 작업을 수행했습니다.
public static final Pattern DIACRITICS_AND_FRIENDS
= Pattern.compile("[\\p{InCombiningDiacriticalMarks}\\p{IsLm}\\p{IsSk}]+");
private static String stripDiacritics(String str) {
str = Normalizer.normalize(str, Normalizer.Form.NFD);
str = DIACRITICS_AND_FRIENDS.matcher(str).replaceAll("");
return str;
}
지정한대로 수행됩니다.
stripDiacritics("Björn") = Bjorn
그러나 ł
문자가 분음 부호가 아니기 때문에 예를 들어 Białystok에서는 실패합니다 .
완전한 문자열 단순화를 원하면 분음 부호가 아닌 특수 문자에 대해 두 번째 정리 라운드가 필요합니다. 이 맵은 고객 이름에 나타나는 가장 일반적인 특수 문자를 포함했습니다. 완전한 목록은 아니지만 확장하는 방법에 대한 아이디어를 제공합니다. immutableMap은 google-collections의 단순한 클래스입니다.
public class StringSimplifier {
public static final char DEFAULT_REPLACE_CHAR = '-';
public static final String DEFAULT_REPLACE = String.valueOf(DEFAULT_REPLACE_CHAR);
private static final ImmutableMap<String, String> NONDIACRITICS = ImmutableMap.<String, String>builder()
//Remove crap strings with no sematics
.put(".", "")
.put("\"", "")
.put("'", "")
//Keep relevant characters as seperation
.put(" ", DEFAULT_REPLACE)
.put("]", DEFAULT_REPLACE)
.put("[", DEFAULT_REPLACE)
.put(")", DEFAULT_REPLACE)
.put("(", DEFAULT_REPLACE)
.put("=", DEFAULT_REPLACE)
.put("!", DEFAULT_REPLACE)
.put("/", DEFAULT_REPLACE)
.put("\\", DEFAULT_REPLACE)
.put("&", DEFAULT_REPLACE)
.put(",", DEFAULT_REPLACE)
.put("?", DEFAULT_REPLACE)
.put("°", DEFAULT_REPLACE) //Remove ?? is diacritic?
.put("|", DEFAULT_REPLACE)
.put("<", DEFAULT_REPLACE)
.put(">", DEFAULT_REPLACE)
.put(";", DEFAULT_REPLACE)
.put(":", DEFAULT_REPLACE)
.put("_", DEFAULT_REPLACE)
.put("#", DEFAULT_REPLACE)
.put("~", DEFAULT_REPLACE)
.put("+", DEFAULT_REPLACE)
.put("*", DEFAULT_REPLACE)
//Replace non-diacritics as their equivalent characters
.put("\u0141", "l") // BiaLystock
.put("\u0142", "l") // Bialystock
.put("ß", "ss")
.put("æ", "ae")
.put("ø", "o")
.put("©", "c")
.put("\u00D0", "d") // All Ð ð from http://de.wikipedia.org/wiki/%C3%90
.put("\u00F0", "d")
.put("\u0110", "d")
.put("\u0111", "d")
.put("\u0189", "d")
.put("\u0256", "d")
.put("\u00DE", "th") // thorn Þ
.put("\u00FE", "th") // thorn þ
.build();
public static String simplifiedString(String orig) {
String str = orig;
if (str == null) {
return null;
}
str = stripDiacritics(str);
str = stripNonDiacritics(str);
if (str.length() == 0) {
// Ugly special case to work around non-existing empty strings
// in Oracle. Store original crapstring as simplified.
// It would return an empty string if Oracle could store it.
return orig;
}
return str.toLowerCase();
}
private static String stripNonDiacritics(String orig) {
StringBuffer ret = new StringBuffer();
String lastchar = null;
for (int i = 0; i < orig.length(); i++) {
String source = orig.substring(i, i + 1);
String replace = NONDIACRITICS.get(source);
String toReplace = replace == null ? String.valueOf(source) : replace;
if (DEFAULT_REPLACE.equals(lastchar) && DEFAULT_REPLACE.equals(toReplace)) {
toReplace = "";
} else {
lastchar = toReplace;
}
ret.append(toReplace);
}
if (ret.length() > 0 && DEFAULT_REPLACE_CHAR == ret.charAt(ret.length() - 1)) {
ret.deleteCharAt(ret.length() - 1);
}
return ret.toString();
}
/*
Special regular expression character ranges relevant for simplification -> see http://docstore.mik.ua/orelly/perl/prog3/ch05_04.htm
InCombiningDiacriticalMarks: special marks that are part of "normal" ä, ö, î etc..
IsSk: Symbol, Modifier see http://www.fileformat.info/info/unicode/category/Sk/list.htm
IsLm: Letter, Modifier see http://www.fileformat.info/info/unicode/category/Lm/list.htm
*/
public static final Pattern DIACRITICS_AND_FRIENDS
= Pattern.compile("[\\p{InCombiningDiacriticalMarks}\\p{IsLm}\\p{IsSk}]+");
private static String stripDiacritics(String str) {
str = Normalizer.normalize(str, Normalizer.Form.NFD);
str = DIACRITICS_AND_FRIENDS.matcher(str).replaceAll("");
return str;
}
}
답변
핵심 java.text 패키지는이 사용 사례 (분음 부호, 대소 문자 등을 고려하지 않고 문자열 일치)를 해결하도록 설계되었습니다.
문자 차이 Collator
를 정렬하도록 a 를 구성합니다 PRIMARY
. 이를 통해 CollationKey
각 문자열에 대해 생성하십시오 . 모든 코드가 Java로되어있는 경우 CollationKey
직접 사용할 수 있습니다. 데이터베이스 나 다른 종류의 인덱스에 키를 저장해야하는 경우 이를 바이트 배열로 변환 할 수 있습니다 .
이러한 클래스는 유니 코드 표준을 사용합니다. 케이스 폴딩 데이터를 동일한 문자를 결정하고 다양한 분해 전략을 지원 합니다.
Collator c = Collator.getInstance();
c.setStrength(Collator.PRIMARY);
Map<CollationKey, String> dictionary = new TreeMap<CollationKey, String>();
dictionary.put(c.getCollationKey("Björn"), "Björn");
...
CollationKey query = c.getCollationKey("bjorn");
System.out.println(dictionary.get(query)); // --> "Björn"
콜 레이터는 로케일에 따라 다릅니다. 이것은 “알파벳 순서”가 로케일마다 다르기 때문입니다 (스페인어의 경우처럼 시간이 지남에 따라). Collator
클래스는이 규칙을 모두 추적하고 최신을 유지하는 데에서 당신을 해소.
답변
이 버전 은 Apache Commons Lang 의 일부입니다 . 3.1.
org.apache.commons.lang3.StringUtils.stripAccents("Añ");
보고 An
답변
다음에서 Normalizer 클래스 를 사용할 수 있습니다 java.text
.
System.out.println(new String(Normalizer.normalize("ń ǹ ň ñ ṅ ņ ṇ ṋ", Normalizer.Form.NFKD).getBytes("ascii"), "ascii"));
그러나 Java는 변환 할 수없는 유니 코드 문자로 이상한 일을 만들기 때문에 여전히해야 할 일이 있습니다 (이 문자를 무시하지 않고 예외를 던지지 않습니다). 그러나 나는 그것을 시작점으로 사용할 수 있다고 생각합니다.
답변
답변
이러한 모든 표시가 의미를 변경하지 않고 제거 할 수있는 일부 “일반”문자의 “표시”는 아닙니다.
스웨덴어에서 å ä와 ö는 다른 문자의 일부 “변형”이 아니라 참되고 적절한 일류 문자입니다. 그들은 다른 모든 문자들과 다르게 들리고, 다르게 분류되며, 단어의 의미를 변경합니다 ( “mätt”와 “matt”는 서로 다른 두 단어입니다).
답변
유니 코드에는 특정 통어 문자 (복합 문자)가 있으며 문자와 통어가 분리되도록 문자열을 변환 할 수 있습니다. 그런 다음 문자열에서 구절을 제거하면 기본적으로 완료됩니다.
정규화, 분해 및 동등성에 대한 자세한 내용은 유니 코드 홈 페이지 에서 유니 코드 표준을 참조하십시오 .
그러나 실제로이를 달성하는 방법은 작업중인 프레임 워크 / OS / …에 따라 다릅니다. .NET을 사용하는 경우 System.Text.NormalizationForm 열거를 허용하는 String.Normalize 메서드를 사용할 수 있습니다 .
