У меня есть строка follwing, и я разделил ее:
>>> st = '%2g%k%3p'
>>> l = filter(None, st.split('%'))
>>> print l
['2g', 'k', '3p']
Теперь я хочу напечатать букву g два раза, одну букву k и букву p три раза:
ggkppp
Как это возможно?
У меня есть строка follwing, и я разделил ее:
>>> st = '%2g%k%3p'
>>> l = filter(None, st.split('%'))
>>> print l
['2g', 'k', '3p']
Теперь я хочу напечатать букву g два раза, одну букву k и букву p три раза:
ggkppp
Как это возможно?
Другим способом является определение вашей функции, которая преобразует 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'
Вы можете использовать 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
Однолинейный путь:
>>> 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'
Предполагается, что вы всегда печатаете одну букву, но предыдущее число может быть длиннее одной цифры в базе 10.
seq = ['2g', 'k', '3p']
result = ''.join(int(s[:-1] or 1) * s[-1] for s in seq)
assert result == "ggkppp"
Завершите список, проверьте первую запись для номера, а затем добавьте вторую цифру вперед:
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:])