Python 유니코드 문자열에서 억양을 제거하는 가장 좋은 방법은 무엇인가?
Python에 유니코드 문자열이 있는데, 모든 억양(다이아크리틱스)을 제거하고 싶다.
나는 웹에서 이것을 하는 우아한 방법을 발견했다. (자바어로)
- 유니코드 문자열을 긴 정규화된 형식으로 변환(문자와 분음 부호 문자)
- 유니코드 유형이 "diacritic"인 모든 문자를 제거하십시오.
PyICU와 같은 라이브러리를 설치해야 하는가, 아니면 Python 표준 라이브러리만으로 이것이 가능한가?그럼 파이선 3호는?
중요 참고:악센트가 없는 문자에 대한 명시적 매핑이 있는 코드는 피하고 싶다.
이것에 대한 정답은 Unidecode이다.그것은 모든 유니코드 문자열을 아스키 텍스트에서 가능한 가장 가까운 표현으로 변환한다.
예:
accented_string = u'Málaga'
# accented_string is of type 'unicode'
import unidecode
unaccented_string = unidecode.unidecode(accented_string)
# unaccented_string contains 'Malaga'and is of type 'str'
이거 어때:
import unicodedata
def strip_accents(s):
return ''.join(c for c in unicodedata.normalize('NFD', s)
if unicodedata.category(c) != 'Mn')
이것은 그리스 문자에도 적용된다.
>>> strip_accents(u"A \u00c0 \u0394 \u038E")
u'A A \u0394 \u03a5'
>>>
문자 범주 "Mn"은Nonspacing_Mark
(MiniQuark의 대답에서 유니코데타.combining과 유사함). 유니코데타.combining은 생각하지 않았지만, 더 노골적이기 때문에 아마도 더 나은 해결책일 것이다.
그리고 이러한 조작은 본문의 의미를 크게 변화시킬 수 있다는 것을 명심하라.억양, 움라우트 등은 "결정"이 아니다.
나는 방금 웹에서 다음과 같은 답을 찾았다.
import unicodedata
def remove_accents(input_str):
nfkd_form = unicodedata.normalize('NFKD', input_str)
only_ascii = nfkd_form.encode('ASCII', 'ignore')
return only_ascii
(예를 들어 프랑스어 같은 경우에는) 잘 작동하지만, 비 ASC를 떨어뜨리는 것보다 두 번째 단계(악센트 제거)가 더 잘 처리될 수 있다고 생각한다.II 문자, 일부 언어(예: 그리스어)에서는 실패하기 때문에가장 좋은 해결책은 아마도 분음 부호화라고 태그된 유니코드 문자를 명시적으로 제거하는 것이 될 것이다.
편집: 유용한 기능:
import unicodedata
def remove_accents(input_str):
nfkd_form = unicodedata.normalize('NFKD', input_str)
return u"".join([c for c in nfkd_form if not unicodedata.combining(c)])
unicodedata.combining(c)
만약 그 캐릭터가 진실로 돌아올 것이다.c
앞의 문자와 결합할 수 있는데, 주로 이음이의 경우 입니다.
편집 2:remove_accents
바이트 문자열이 아닌 유니코드 문자열을 예상한다.바이트 문자열이 있으면 다음과 같은 유니코드 문자열로 디코딩해야 한다.
encoding = "utf-8" # or iso-8859-15, or cp1252, or whatever encoding you use
byte_string = b"café" # or simply "café" before python 3.
unicode_string = byte_string.decode(encoding)
사실 프로젝트 호환 python 2.6, 2.7, 3.4를 작업하고 있는데 무료 사용자 항목에서 ID를 만들어야 해.
당신 덕분에, 나는 경이로운 이 기능을 만들어냈어.
import re
import unicodedata
def strip_accents(text):
"""
Strip accents from input String.
:param text: The input string.
:type text: String.
:returns: The processed String.
:rtype: String.
"""
try:
text = unicode(text, 'utf-8')
except (TypeError, NameError): # unicode is a default on python 3
pass
text = unicodedata.normalize('NFD', text)
text = text.encode('ascii', 'ignore')
text = text.decode("utf-8")
return str(text)
def text_to_id(text):
"""
Convert input text to id.
:param text: The input string.
:type text: String.
:returns: The processed String.
:rtype: String.
"""
text = strip_accents(text.lower())
text = re.sub('[ ]+', '_', text)
text = re.sub('[^0-9a-zA-Z_-]', '', text)
return text
결과:
text_to_id("Montréal, über, 12.89, Mère, Françoise, noël, 889")
>>> 'montreal_uber_1289_mere_francoise_noel_889'
이것은 억양뿐만 아니라 (ø 등) "스트로크"도 다룬다.
import unicodedata as ud
def rmdiacritics(char):
'''
Return the base character of char, by "removing" any
diacritics like accents or curls and strokes and the like.
'''
desc = ud.name(char)
cutoff = desc.find(' WITH ')
if cutoff != -1:
desc = desc[:cutoff]
try:
char = ud.lookup(desc)
except KeyError:
pass # removing "WITH ..." produced an invalid name
return char
이것이 내가 생각할 수 있는 가장 우아한 방법이다(그리고 알렉시스가 이 페이지의 논평에서 언급한 바 있다). 비록 나는 이것이 그다지 우아하다고는 생각하지 않는다.사실, 그것은 코멘트에서 지적했듯이, 유니코드 이름들은 이름뿐이기 때문에 해킹에 더 가깝고, 일관적이거나 어떤 것이든 보장할 수 없다.
유니코드 이름에는 'WITH'가 들어 있지 않기 때문에, 여전히 반전 문자, 반전 문자 등 이것에 의해 처리되지 않는 특별한 문자가 있다.어차피 네가 하고 싶은 일에 달려 있어.나는 사전 정렬 순서를 맞추기 위해 때때로 액센트 박제가 필요했다.
주 편집:
코멘트의 제안사항(검색 오류 처리, Python-3 코드) 포함.
@MiniQuark의 대답에 대해 다음과 같이 대답한다.
나는 csv 파일로 읽으려고 했는데, 그것은 반은 프랑스어였고, 또한 어떤 문자열은 결국 정수와 부유물이 될 것이다.테스트로, 나는test.txt
다음과 같은 파일:
몬트레알, 뷔르, 12.89, 메레, 프랑수아즈, 노엘, 889
나는 대사를 포함해야만 했다.2
, 그리고3
@Jabba의 코멘트를 통합할 뿐만 아니라 (내가 파이톤 티켓에서 찾은) 그것을 작동시키기 위해.
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
import csv
import unicodedata
def remove_accents(input_str):
nkfd_form = unicodedata.normalize('NFKD', unicode(input_str))
return u"".join([c for c in nkfd_form if not unicodedata.combining(c)])
with open('test.txt') as f:
read = csv.reader(f)
for row in read:
for element in row:
print remove_accents(element)
결과:
Montreal
uber
12.89
Mere
Francoise
noel
889
(참고: Mac OS X 10.8.4에서 Python 2.7.3을 사용하고 있음)
Gensim.utils.deaccent(텍스트) - 인간을 위한 주제 모델링:
'Sef chomutovskych komunistu dostal postou bily prasek'
또 다른 해결책은 비이데코드다.
유니코다타를 사용한 제안 솔루션은 일반적으로 일부 문자에서만 억양을 제거한다는 점에 유의하십시오(예: 변한다).'ł'
''
속으로가 아니라,'l'
).
import unicodedata
from random import choice
import perfplot
import regex
import text_unidecode
def remove_accent_chars_regex(x: str):
return regex.sub(r'\p{Mn}', '', unicodedata.normalize('NFKD', x))
def remove_accent_chars_join(x: str):
# answer by MiniQuark
# https://stackoverflow.com/a/517974/7966259
return u"".join([c for c in unicodedata.normalize('NFKD', x) if not unicodedata.combining(c)])
perfplot.show(
setup=lambda n: ''.join([choice('Málaga François Phút Hơn 中文') for i in range(n)]),
kernels=[
remove_accent_chars_regex,
remove_accent_chars_join,
text_unidecode.unidecode,
],
labels=['regex', 'join', 'unidecode'],
n_range=[2 ** k for k in range(22)],
equality_check=None, relative_to=0, xlabel='str len'
)
내가 볼 때, 제안된 해결책들은 답변이 받아들여져서는 안 된다.원래 질문은 억양을 제거해 달라는 것이므로 정답은 그것과 더불어 다른 불특정하고 불특정화된 변화만 함께 하지 말고 그것만 해야 한다.
이 코드의 결과를 단순히 준수하십시오. 이 코드는 합격된 답입니다.내가 "말라가"를 "말라가"로 바꾼 곳:
accented_string = u'Málagueña'
# accented_string is of type 'unicode'
import unidecode
unaccented_string = unidecode.unidecode(accented_string)
# unaccented_string contains 'Malaguena'and is of type 'str'
OQ에서는 요청되지 않은 추가 변경(n -> n)이 있다.
요청된 작업을 낮은 형식으로 수행하는 간단한 기능:
def f_remove_accents(old):
"""
Removes common accent characters, lower form.
Uses: regex.
"""
new = old.lower()
new = re.sub(r'[àáâãäå]', 'a', new)
new = re.sub(r'[èéêë]', 'e', new)
new = re.sub(r'[ìíîï]', 'i', new)
new = re.sub(r'[òóôõö]', 'o', new)
new = re.sub(r'[ùúûü]', 'u', new)
return new
어떤 언어는 언어 문자로 분음 부호를 조합하고 액센트를 지정하기 위해 분음 부호를 조합한다.
나는 당신이 벗겨내고자 하는 diactrics를 명시적으로 명시하는 것이 더 안전하다고 생각한다.
def strip_accents(string, accents=('COMBINING ACUTE ACCENT', 'COMBINING GRAVE ACCENT', 'COMBINING TILDE')):
accents = set(map(unicodedata.lookup, accents))
chars = [c for c in unicodedata.normalize('NFD', string) if c not in accents]
return unicodedata.normalize('NFC', ''.join(chars))
Elasticsearch의 기능과 유사한 기능을 얻고자 하는 경우asciifolding
필터(fold-to-ascy)를 고려해 보십시오. [fold-to-ascy], 즉 [fold-to-
Apache Lucene ASCII 폴딩 필터의 Python 포트로서, 처음 127개의 ASCII 문자("Basic Latin" Unicode Block")에 없는 알파벳, 숫자 및 심볼 유니코드 문자를 ASCII 동등 문자(있는 경우)로 변환한다.
위에 언급된 페이지의 예는 다음과 같다.
from fold_to_ascii import fold
s = u'Astroturf® paté'
fold(s)
> u'Astroturf pate'
fold(s, u'?')
> u'Astroturf? pate'
편집: Thefold_to_ascii
모듈은 라틴어 기반의 알파벳을 정상화하는 데 효과가 있는 것 같다. 그러나 이 모듈에서는 표시 불가능한 문자가 제거된다. 이는 이 모듈이 예를 들어 문자열을 비우는 것과 같은 중국어 텍스트를 줄인다는 것을 의미한다.중국어, 일본어 및 기타 유니코드 알파벳을 보존하려면 @mo-han의 알파벳을 사용하는 것을 고려하십시오.remove_accent_chars_regex
상기 구현.
'Programing' 카테고리의 다른 글
Vuetify에서 v-card 구성 요소의 중앙에 콘텐츠를 맞추는 방법 (0) | 2022.03.13 |
---|---|
vuex에서 스토어 값을 보는 방법? (0) | 2022.03.13 |
Algolia InstantSearch Vue 구성 요소를 Vuetify 데이터 테이블에 통합 (0) | 2022.03.13 |
파이톤 3의 로_input()과 인풋()의 차이점은 무엇일까. (0) | 2022.03.13 |
반응 후크가 있는 두 번째 루프에서만 작동하는 루프용 (0) | 2022.03.13 |