Python: как я могу заменить символы полной ширины символами половины ширины?
Если бы это был PHP, я бы, вероятно, сделал что-то вроде этого:
function no_more_half_widths($string){
$foo = array('1','2','3','4','5','6','7','8','9','10')
$bar = array('1','2','3','4','5','6','7','8','9','10')
return str_replace($foo, $bar, $string)
}
Я пробовал .функция translate в python и указывает, что массивы не имеют одинакового размера. Я предполагаю, что это связано с тем, что отдельные символы кодируются в UTF-8. Есть предложения?
6 ответов
встроенный unicodedata
модуль может сделать это:
>>> import unicodedata
>>> foo = u'1234567890'
>>> unicodedata.normalize('NFKC', foo)
u'1234567890'
"NFKC " означает"Форма Нормализации KC [декомпозиция совместимости, за которой следует каноническая композиция]", и заменяет символы полной ширины на символы половинной ширины, которые являются эквивалент в Юникоде.
обратите внимание, что он также нормализует все виды других вещей одновременно, как отдельные знаки акцента и римские цифры.
в Python3 вы можете использовать следующий фрагмент. Он сделал карту между всеми символами ascii и соответствующим символом полной ширины. Лучше всего, это не нужно вам жесткий тип последовательности ascii, который довольно подвержен ошибкам.
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
FULL2HALF = dict((i + 0xFEE0, i) for i in range(0x21, 0x7F))
FULL2HALF[0x3000] = 0x20
def halfen(s):
'''
Convert full-width characters to ASCII counterpart
'''
return str(s).translate(FULL2HALF)
кроме того, с той же логикой вы можете конвертировать символы halfwidth в символ fullwidth, следующий код показывает трюк:
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
HALF2FULL = dict((i, i + 0xFEE0) for i in range(0x21, 0x7F))
HALF2FULL[0x20] = 0x3000
def fullen(s):
'''
Convert all ASCII characters to the full-width counterpart.
'''
return str(s).translate(HALF2FULL)
примечание: эти два фрагмента рассматривают только символы ascii и не преобразуют их японский / корейский fullwidth характер.
для полноты картины от wikepedia:
ряд
U+FF01–FF5E
воспроизводит характеры ASCII 21 К 7E как формы fullwidth, то есть форма фиксированной ширины, используемая в CJK вычисления. Это полезно для набора латинских символов в CJK окружающая среда.U+FF00
не соответствует полной ширине ASCII 20 (символ пространства), так как эта роль уже выполняетсяU+3000
"идеографическое пространство."ряд
U+FF65–FFDC
кодирует формы половинной ширины катаканы и хангыля письмена.ряд
U+FFE0–FFEE
включает символы fullwidth и halfwidth.
и более, решение python2 может ссылаться на gist / jcayzac
Я не думаю, что есть встроенная функция для выполнения нескольких замен за один проход, поэтому вам придется сделать это самостоятельно.
один из способов сделать это:
>>> src = (u'1',u'2',u'3',u'4',u'5',u'6',u'7',u'8',u'9',u'10')
>>> dst = ('1','2','3','4','5','6','7','8','9','0')
>>> string = u'a123'
>>> for i, j in zip(src, dst):
... string = string.replace(i, j)
...
>>> string
u'a123'
или с помощью словаря:
>>> trans = {u'1': '1', u'2': '2', u'3': '3', u'4': '4', u'5': '5', u'6': '6', u'7': '7', u'8': '8', u'9': '9', u'0': '0'}
>>> string = u'a123'
>>> for i, j in trans.iteritems():
... string = string.replace(i, j)
...
>>> string
u'a123'
или, наконец, с помощью regex (и это может быть самый быстрый):
>>> import re
>>> trans = {u'1': '1', u'2': '2', u'3': '3', u'4': '4', u'5': '5', u'6': '6', u'7': '7', u'8': '8', u'9': '9', u'0': '0'}
>>> lookup = re.compile(u'|'.join(trans.keys()), re.UNICODE)
>>> string = u'a123'
>>> lookup.sub(lambda x: trans[x.group()], string)
u'a123'
С помощью unicode.translate
способ:
>>> table = dict(zip(map(ord,u'0123456789'),map(ord,u'0123456789')))
>>> print u'123'.translate(table)
123
требуется отображение кодовых точек как цифры, а не персонажей. Кроме того, используя u'unicode literals'
оставляет значения некодированные.
Regex подход
>>> import re
>>> re.sub(u"[\uff10-\uff19]",lambda x:chr(ord(x.group(0))-0xfee0),u"456")
u'456'
в Python 3, cleanest должен использовать .перевести и .maketrans:
FULLWIDTH_TO_HALFWIDTH = str.maketrans('1234567890',
'1234567890')
def fullwidth_to_halfwidth(s):
return s.translate(FULLWIDTH_TO_HALFWIDTH)
в Python 2, str.maketrans вместо строку.maketrans и не работает с символами Юникода, поэтому вам нужно сделать словарь, как отмечает Джош ли выше.