Добавление подстрочного форматирования ко всем числам в строке - PullRequest
2 голосов
/ 28 января 2020

Я пытаюсь написать простой сценарий, который выполняет итерацию по входной строке и преобразует все числа в строке в индексы с номерами.

Вот моя последняя попытка выполнить итерацию по входной строке item и должен создать новую строку, содержащую подписанные числа вместо чисел в исходной строке. Может быть, это невозможно, но я не могу объединить Unicode и форматировать строковые литеральные выражения, чтобы сделать эту работу.

item= 'H2O'
new=[]

sub = u'\u208'

for i,x in enumerate(item):
    if x.isdigit():
        sub=u'{x}'.format(sub)
        new.append(sub)
    else:
        new.append(x)
new=''.join(new)

new

Я получаю следующую ошибку:

File "<ipython-input-48-1d7d4a7394db>", line 4
    sub = u'\u208'
         ^
SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 0-4: truncated \uXXXX escape

В В конце я хотел бы сделать следующее «преобразование», чтобы получить «номерную» версию (H₂O) входной строки (H2O):

H2O --> H₂O

Любые мысли о том, что Я делаю неправильно или, может быть, есть лучший способ сделать это? Спасибо!

Ответы [ 3 ]

4 голосов
/ 28 января 2020

Вы можете использовать str.maketrans().

u'\u2080' до u'\u2089' представляют числа от 0 до 9

sub=str.maketrans("0123456789", "₀₁₂₃₄₅₆₇₈₉")
_str='C3H8O3'
_str=_str.translate(sub)
print(_str)

вывод

'C₃H₈O₃'

В вашем коде sub=u'\u208' должно быть sub=u'\u2082'. Простой замены было бы достаточно.

_str='H2O'
sub=u'\u2082'
for char in _str:
    if char.isdigit():
        _str=_str.replace(char,sub)
print(_str)

'H₂O'

Построение нормальных значений в словаре значений индекса.

sub=u'\u2080'
norm_to_sub={}
for norm in '0123456789':
    norm_to_sub[norm]=sub
    sub=chr(ord(sub)+1)

print(norm_to_sub)

{'0': '₀', '1': '₁', '2': '₂', '3': '₃', '4': '₄', '5': '₅', '6': '₆', '7': '₇', '8': '₈', '9': '₉'}

Как и предполагалось с помощью wjandrea вы можете сделать это.

sub = 0x2080
norm_to_sub={}
for norm in range(10):
    norm_to_sub[norm] = ord(sub + norm)

{'0': '₀', '1': '₁', '2': '₂', '3': '₃', '4': '₄', '5': '₅', '6': '₆', '7': '₇', '8': '₈', '9': '₉'}

Вы даже можете создать функцию.

def change_to_sub(number):
    sub=0x2080
    return ''.join(chr(sub+int(num)) for num in str(number))

print(change_to_sub(1232454353654))

'₁₂₃₂₄₅₄₃₅₃₆₅₄'
0 голосов
/ 28 января 2020

Ваша реализация не имеет смысла, но ваш подход делает. Что вы можете сделать, это взять целочисленное значение di git, добавить 0x2080, чтобы получить кодовую точку индекса, а затем преобразовать в символ.

import string

item = 'H2O'
sub = 0x2080
new = ''.join(chr(sub + int(c)) if c in string.digits else c for c in item)
print(new)  # -> H₂O

Я использую string.digits здесь, потому что str.isdigit делает больше, чем вы хотите. Он вернет true для строк, которые не могут быть преобразованы в целые, например, '₂'.

0 голосов
/ 28 января 2020

С точки зрения методологии, можно сократить операцию на два-два шага. Я думаю, что это также помогает с удобочитаемостью и, если потребуется в будущем, может позволить вам делать такие вещи, как более легкую векторизацию вашей операции:

>>> mapping = {"0": "₀", "1": "₁", "2": "₂", "3": "₃", "4": "₄", 
               "5": "₅", "6": "₆", "7": "₇", "8": "₈", "9": "₉"}
>>> formula = "CH3CH2CH2CH3"
>>> "".join([mapping.get(x) or x for x in list(formula)])
'CH₃CH₂CH₂CH₃'

Что касается ошибки Unicode, которую вы получаете, я получаю та же ошибка в юпитер. Но вставка символов из википедии прямо в ячейку моего ноутбука, похоже, решает проблему.

Если вы действительно хотите использовать юникод-коды, похоже, вы пропустили последний символ кода. Таким образом, должно быть '\u2080' (python3) или u'\u2080' (python2), - это '\u2081', et c.

...