Czy istnieje lepszy sposób na pozbycie się akcentów i regularne pisanie tych liter oprócz używania String.replaceAll()
metody i zastępowania liter jedna po drugiej? Przykład:
Wejście: orčpžsíáýd
Wynik: orcpzsiayd
Nie musi zawierać wszystkich liter z akcentami, takimi jak alfabet rosyjski lub chiński.
java
string
diacritics
Jaskółka oknówka
źródło
źródło
string.replaceAll("\\p{M}", "")
. Aby uzyskać więcej informacji, zobacz regular-expressions.info/unicode.html .Począwszy od 2011 roku możesz używać Apache Commons StringUtils.stripAccents (dane wejściowe) (od 3.0):
Uwaga:
Przyjęta odpowiedź (odpowiedź Ericka Robertsona) nie działa dla Ø ani Ł. Apache Commons 3.5 też nie działa na Ø, ale działa na Ł. Po przeczytaniu artykułu z Wikipedii dotyczącego Ø , nie jestem pewien, czy należy go zastąpić „O”: jest to osobna litera w języku norweskim i duńskim, alfabetycznie po „z”. To dobry przykład ograniczeń podejścia „strip accents”.
źródło
Rozwiązanie @ virgo47 jest bardzo szybkie, ale przybliżone. W zaakceptowanej odpowiedzi użyto Normalizera i wyrażenia regularnego. Zastanawiałem się, jaka część czasu zajęła Normalizer a wyrażenie regularne, ponieważ usunięcie wszystkich znaków spoza ASCII można wykonać bez wyrażenia regularnego:
Małe dodatkowe przyspieszenia można uzyskać, pisząc do char [] i nie wywołując metodyCharArray (), chociaż nie jestem pewien, czy zasługuje na to zmniejszenie przejrzystości kodu:
Ta odmiana ma tę zaletę, że poprawność tej przy użyciu Normalizera i pewnej prędkości tej przy użyciu tabeli. Na moim komputerze ten jest około 4x szybszy niż zaakceptowana odpowiedź i 6,6x do 7x wolniejszy niż @ virgo47 (akceptowana odpowiedź jest około 26x wolniejsza niż @ virgo47 na moim komputerze).
źródło
out
należy zmienić rozmiar, aby dopasować liczbę prawidłowych znaków,j
zanim zostanie on użyty do skonstruowania obiektu ciąguflattenToAscii
tworzy wynik „aa ..”, w którym kropki oznaczają \ u0000. To nie jest dobre. Pierwsze pytanie brzmi - jak reprezentować „nienormalne” postacie? Powiedzmy, że tak będzie, czy możemy zostawić tam znak NULL, ale w każdym razie musimy zachować ich prawidłowe położenie (podobnie jak rozwiązanie wyrażenia regularnego). W tym celu if w pętli musi być coś w stylu:if (c <= '\u007F') out[j++] = c; else if (Character.isLetter(c)) out[j++] = '?';
Spowolni to nieco, ale przede wszystkim musi być poprawne. ;-)isLetter
) nie jest właściwe, ale nie znalazłem lepszego. Nie jestem ekspertem od Unicode, więc nie wiem, jak lepiej zidentyfikować klasę pojedynczego znaku, który zastępuje oryginalny znak. Listy działają OK dla większości aplikacji / zastosowań.EDYCJA: Jeśli nie utkniesz z Javą <6, a szybkość nie jest krytyczna i / lub tabela tłumaczeń jest zbyt ograniczona, skorzystaj z odpowiedzi Davida. Chodzi o to, aby użyć
Normalizer
(wprowadzonego w Javie 6) zamiast tabeli translacji wewnątrz pętli.Chociaż nie jest to „idealne” rozwiązanie, działa dobrze, gdy znasz zakres (w naszym przypadku Latin1,2), działał przed Javą 6 (choć nie jest to prawdziwy problem) i jest znacznie szybszy niż najbardziej sugerowana wersja (może lub może nie stanowić problemu):
Testy na moim HW z 32-bitowym JDK pokazują, że wykonuje konwersję z àèéľšťč89FDČ do aeelstc89FDC 1 milion razy w ~ 100ms, podczas gdy sposób Normalizera robi to w 3,7s (37x wolniej). Jeśli Twoje potrzeby dotyczą wydajności i znasz zakres wejściowy, może to być dla Ciebie.
Cieszyć się :-)
źródło
pracował dla mnie. Wyjście powyższego fragmentu daje „aee”, co chciałem, ale
nie dokonał żadnej zamiany.
źródło
W zależności od języka mogą to nie być akcenty (które zmieniają dźwięk litery), ale znaki diakrytyczne
https://en.wikipedia.org/wiki/Diacritic#Languages_with_letters_containing_diacritics
„Bośniacki i chorwacki mają symbole č, ć, đ, š i ž, które są uważane za osobne litery i są wymienione jako takie w słownikach i innych kontekstach, w których słowa są wymienione zgodnie z kolejnością alfabetyczną.”
Ich usunięcie może z natury zmienić znaczenie słowa lub zmienić litery na zupełnie inne.
źródło
Napotkałem ten sam problem związany z kontrolą równości ciągów, jeden z ciągów porównawczych ma kod znakowy ASCII 128-255 .
Użyj poniższego kodu dla różnych spacji i ich kodów bajtowych:
wiki for List_of_Unicode_characters
Transl Transliteracje ASCII ciągu Unicode dla Java.
unidecode
➩ przy użyciu
Guava
: Google CoreLibraries for Java
.Do kodowania adresu URL miejsca użyj biblioteki Guava.
➩ W celu przezwyciężenia tego problemu zastosowano go
String.replaceAll()
z niektórymiRegularExpression
.➩ Korzystanie z java.text.Normalizer.Form . To wyliczenie zapewnia stałe czterech form normalizacji Unicode opisanych w Aneksie Standardu Unicode nr 15 - Formy normalizacji Unicode i dwie metody dostępu do nich.
Testowanie napisów i danych wyjściowych w różnych podejściach, takich jak d Unidecode, Normalizer, StringUtils .
Użycie Unidecode to
best choice
Mój kod końcowy pokazany poniżej.źródło
Sugeruję kod Junidecode . Będzie obsługiwał nie tylko „Ł” i „Ø”, ale również dobrze sprawdza się w przypadku transkrypcji z innych alfabetów, takich jak chiński, na alfabet łaciński.
źródło
Rozwiązanie Davida Conrada jest najszybsze, jakie próbowałem użyć Normalizatora, ale ma błąd. Zasadniczo usuwa znaki, które nie są akcentami, na przykład chińskie znaki i inne litery, takie jak æ, są usuwane. Znaki, które chcemy usunąć, to znaki spacji, znaki, które nie zajmują dodatkowej szerokości w końcowym ciągu. Te znaki o zerowej szerokości w zasadzie łączą się w jakiś inny znak. Jeśli widzisz, że są odizolowane jako postać, na przykład jak ten `, zgaduję, że jest to połączone ze znakiem spacji.
źródło
Jednym z najlepszych sposobów używania wyrażeń regularnych i Normalizatora, jeśli nie masz biblioteki, jest:
Jest to bardziej wydajne niż replaceAll („[^ \ p {ASCII}]”, „”)) i jeśli nie potrzebujesz znaków diakrytycznych (tak jak w twoim przykładzie).
W przeciwnym razie musisz użyć wzorca p {ASCII}.
Pozdrowienia.
źródło
Myślę, że najlepszym rozwiązaniem jest konwersja każdego znaku na HEX i zastąpienie go innym HEX. Jest tak, ponieważ istnieją 2 typy pisania w Unicode:
Na przykład „Ồ” napisane przez Unicode kompozytowe różni się od „Ồ” napisanego przez wstępnie skomponowany Unicode. Możesz skopiować moje przykładowe znaki i przekonwertować je, aby zobaczyć różnicę.
Opracowałem tę funkcję dla niektórych banków do konwersji informacji przed wysłaniem ich do banku podstawowego (zwykle nie obsługują Unicode) i napotkałem ten problem, gdy użytkownicy końcowi używają wielu typów Unicode do wprowadzania danych. Więc myślę, że konwersja na HEX i zamiana jest najbardziej niezawodnym sposobem.
źródło
W przypadku, gdy ktoś próbuje to zrobić w kotlin, ten kod działa jak urok. Aby uniknąć niespójności, używam również .toUpperCase i Trim (). następnie rzutuję tę funkcję:
}
aby skorzystać z tej zabawy, wyślij kod w ten sposób:
źródło