Подтвердить что ты не робот

Печать писем в определенном шаблоне в Python

У меня есть строка follwing, и я разделил ее:

>>> st = '%2g%k%3p'
>>> l = filter(None, st.split('%'))
>>> print l
['2g', 'k', '3p']

Теперь я хочу напечатать букву g два раза, одну букву k и букву p три раза:

ggkppp

Как это возможно?

4b9b3361

Ответ 1

ПОЗЖЕ НА ВЫСТАВКЕ, НО ГОТОВЫ К GO

Другим способом является определение вашей функции, которая преобразует nC в CCCC... C (ntimes), затем передайте ее в map, чтобы применить ее к каждому элементу списка l, исходящему из split над %, наконец, join все они:

>>> def f(s):
        x = 0
        if s:
            if len(s) == 1:
                out = s
            else:
                for i in s:
                    if i.isdigit():
                        x = x*10 + int(i)
                out = x*s[-1]

        else:
            out = ''
        return out

>>> st
'%4g%10k%p'
>>> ''.join(map(f, st.split('%')))
'ggggkkkkkkkkkkp'
>>> st = '%2g%k%3p'
>>> ''.join(map(f, st.split('%')))
'ggkppp'

Или, если вы хотите поместить все это в одно определение функции:

>>> def f(s):
        out = ''
        if s:
            l = filter(None, s.split('%'))
            for item in l:
                x = 0
                    if len(item) == 1:
                        repl = item
                    else:
                        for c in item:
                            if c.isdigit():
                                x = x*10 + int(c)
                        repl = x*item[-1]
                    out += repl

        return out

>>> st
'%2g%k%3p'
>>> f(st)
'ggkppp'
>>> 
>>> st = '%4g%10k%p'
>>> 
>>> f(st)
'ggggkkkkkkkkkkp'
>>> st = '%4g%101k%2p'
>>> f(st)
'ggggkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkpp'
>>> len(f(st))
107

EDIT:

В случае наличия _, где OP не хочет, чтобы этот символ повторялся, лучшим способом, на мой взгляд, является re.sub, это упростит ситуацию следующим образом:

>>> def f(s):
        pat = re.compile(r'%(\d*)([a-zA-Z]+)')
        out = pat.sub(lambda m:int(m.group(1))*m.group(2) if m.group(1) else m.group(2), s)
        return out

>>> st = '%4g_%12k%p__%m'
>>> f(st)
'gggg_kkkkkkkkkkkkp__m'

Ответ 2

Вы можете использовать generator с isdigit(), чтобы проверить, что ваш первый символ является цифрой или нет, а затем возвращает следующую строку с соответствующим подсчетом. Затем вы можете использовать join для получения результата:

''.join(i[1:]*int(i[0]) if i[0].isdigit() else i for i in l)

Демонстрация:

In [70]: [i[1:]*int(i[0]) if i[0].isdigit() else i for i in l ]
Out[70]: ['gg', 'k', 'ppp']

In [71]: ''.join(i[1:]*int(i[0]) if i[0].isdigit() else i for i in l)
Out[71]: 'ggkppp'

ИЗМЕНИТЬ

Использование модуля re при первом номере с несколькими цифрами:

''.join(re.search('(\d+)(\w+)', i).group(2)*int(re.search('(\d+)(\w+)', i).group(1)) if re.search('(\d+)(\w+)', i) else i for i in l)

Пример:

In [144]: l = ['12g', '2kd', 'h', '3p']

In [145]: ''.join(re.search('(\d+)(\w+)', i).group(2)*int(re.search('(\d+)(\w+)', i).group(1)) if re.search('(\d+)(\w+)', i) else i for i in l)
Out[145]: 'ggggggggggggkdkdhppp'

EDIT2

Для ввода:

st = '%2g_%3k%3p'

Вы можете заменить _ пустой строкой, а затем добавить _ в конец, если работа из списка заканчивается символом _:

st = '%2g_%3k%3p'
l = list(filter(None, st.split('%')))
''.join((re.search('(\d+)(\w+)', i).group(2)*int(re.search('(\d+)(\w+)', i).group(1))).replace("_", "") + '_' * i.endswith('_') if re.search('(\d+)(\w+)', i) else i for i in l)

Вывод:

'gg_kkkppp'

EDIT3

Решение без модуля re, но с обычными циклами, работающими на 2 цифры. Вы можете определить функции:

def add_str(ind, st):
    if not st.endswith('_'):
        return st[ind:] * int(st[:ind])
    else:
        return st[ind:-1] * int(st[:ind]) + '_'

def collect(l):
    final_str = ''
    for i in l:
        if i[0].isdigit():
            if i[1].isdigit():
                final_str += add_str(2, i)
            else:
                final_str += add_str(1, i)
        else:
            final_str += i
    return final_str

И затем используйте их как:

l = ['12g_', '3k', '3p']

print(collect(l))
gggggggggggg_kkkppp

Ответ 3

Однолинейный путь:

>>> import re
>>> st = '%2g%k%3p'
>>> re.sub(r'%|(\d*)(\w+)', lambda m: int(m.group(1))*m.group(2) if m.group(1) else m.group(2), st)
'ggkppp'

%|(\d*)(\w+) regex соответствует всем % и фиксирует нуль или moredigit, присутствующие перед любым символом слова, в одну группу и следующие словарные символы в другую группу. При замене все согласованные символы следует заменить на значение, указанное в запасной части. Поэтому это должно потерять символ %.

или

>>> re.sub(r'%(\d*)(\w+)', lambda m: int(m.group(1))*m.group(2) if m.group(1) else m.group(2), st)
'ggkppp'

Ответ 4

Предполагается, что вы всегда печатаете одну букву, но предыдущее число может быть длиннее одной цифры в базе 10.

seq = ['2g', 'k', '3p']
result = ''.join(int(s[:-1] or 1) * s[-1] for s in seq)
assert result == "ggkppp"

Ответ 5

Завершите список, проверьте первую запись для номера, а затем добавьте вторую цифру вперед:

string=''
l = ['2g', 'k', '3p']
for entry in l:
    if len(entry) ==1:
        string += (entry)
    else:
        number = int(entry[0])
        for i in range(number):
            string += (entry[1:])