fbpx

Замена подстроки значениями из списка

298 просмотра
0
0 Комментариев

Есть строка:

 "$1.234.567,89 gjhv $1.02 $1.203,20 ghjb $1.205 $63"

и есть список:

 ['$1,234,567.89', '$1.02', '$1,203.20', '$1,205', '$63']

Как заменить каждую сумму в строке соответствующим значением из списка? Порядок значений в списке соответствует порядку в строке.
Я в регулярных выражениях не сильна. Пробовала с помощью метода sub и вызовом функции внутри него, но функция возвращает только первое значение списка (или просто метод sub берёт только первое значение).

import re
text = "$1.234.567,89 gjhv $1.02 $1.203,20 ghjb $1.205 $63"
numbers_list = ['$1,234,567.89', '$1.02', '$1,203.20', '$1,205', '$63']
def num(n):
    for n in numbers_list:
        return n
 
a = re.sub(r'\$[\d,.]*\b', num, text)


Добавить комментарий

4 Answers

Python Опубликовано 19.01.2019
0

У вас все верно сделано, кроме функции num(n). При каждом вызове она читает список numbers_list и возвращает его первый элемент. Чтобы вы не меняли весь код, попробуйте сделать так:

def num(n):
    for n in numbers_list:
        numbers_list.remove(n)
        return n

Это позволит получать нужный элемент из списка, но он будет «очищаться». Если он нужен в целом виде, можете создать его копию

Добавить комментарий
0

Можно создать итератор из списка и получать следующее значение с помощью next():

import re
text = "$1.234.567,89 gjhv $1.02 $1.203,20 ghjb $1.205 $63"
numbers_list = ['$1,234,567.89', '$1.02', '$1,203.20', '$1,205', '$63']
it = iter(numbers_list) # Создаем итератор
 
def replacer(match):    # Обрабатываем совпадение
    return next(it)     # Возвращаем значение и передвигаем индекс итератора
 
print(re.sub(r'\$\d[\d,.]*\b', replacer, text))
# => $1,234,567.89 gjhv $1.02 $1,203.20 ghjb $1,205 $63

См. демо онлайн

А ещё вот одно решение оригинальной проблемы (преобразование чисел из одного формата в другой):

import re, locale
 
text = "$1.234.567,89 gjhv $1.02 $1.203,20 ghjb $1.205 $63"
 
def repl(m):
    fraction = len(m.group(2)) if m.group(2) else 0
    locale.setlocale(locale.LC_NUMERIC, 'en_US')
    return "${}".format(locale.format("%.{}f".format(fraction), float(m.group(1).replace(".","").replace(",", ".")), True))
 
print(re.sub(r'\$(\d{1,3}(?:\.\d{3})*(?:,(\d+))?)', repl, text))
# => $1,234,567.89 gjhv $1.02 $1,203.20 ghjb $1,205 $63

Ещё одно демо

Тут \$(\d{1,3}(?:\.\d{3})*(?:,(\d+))?) находит числа после $ в формате x.xxx,xxxxxx, конвертирует число в американский английский формат (locale.format("%.{}f".format(fraction), float(m.group(1).replace(".","").replace(",", ".")), True)) с соблюдением количества цифр после запятой (см.
fraction, определяемой как len(m.group(2)) if m.group(2) else 0).

Добавить комментарий
0

Если вы хотите заменить в денежных суммах запятые на точки и наоборот точки на запятые:

>>> import re
>>> re.sub(r'\$[\d,.]+', lambda m: m.group().replace(',', '\0').replace('.', ',').replace('\0', '.'), text)
'$1,234,567.89 gjhv $1,02 $1,203.20 ghjb $1,205 $63'

Это предполагает, что в тексте нет U+0000 символа (крайне вероятно).

Если просто каждую сумму на последующий элемент списка хотите заменить, то итератор можно использовать:

>>> replacements = ['$1,234,567.89', '$1.02', '$1,203.20', '$1,205', '$63']
>>> re.sub(r'\$[\d,.]+', lambda _, it=iter(replacements): next(it), text)
'$1,234,567.89 gjhv $1.02 $1,203.20 ghjb $1,205 $63'

Возможно, при создании текста, следует сразу правильное форматирование использовать:

>>> import locale
>>> locale.setlocale(locale.LC_MONETARY, 'en_US.UTF-8')  # the name is platform dependent
'en_US.UTF-8'
>>> [locale.currency(amount, grouping=True) for amount in money]
['$1,234,567.89', '$1.02', '$1,203.20', '$1,205.00', '$63.00']

Чтобы не менять глобальную locale (полезно в многопоточных приложениях и для переносимости), можно babel модуль использовать:

>>> from decimal import Decimal
>>> from babel.numbers import format_currency  # $ pip install babel
>>> amount = Decimal('1234567.89')
>>> print(format_currency(amount, 'USD', locale='en_US'))
$1,234,567.89
>>> print(format_currency(amount, 'RUR', locale='ru_RU'))
1 234 567,89 р.

Добавить комментарий
0

Я бы поработал над листом значений. Создай из него список словарей где ключ будет строка с поменяными точками и запятыми. Потом можно искать ключ в строке и заменять на значение.

Добавить комментарий
Напишите свой ответ на данный вопрос.
Scroll Up