Python: заменить i-е вхождение x на i-й элемент в списке

#python #string #replace #loops #substitution

#python #строка #заменить #циклы #замена

Вопрос:

Предположим, у нас есть строка a = "01000111000011" с n=5 "1" s. i-й "1" символ я хотел бы заменить на i-й символ в "ORANGE" . Мой результат должен выглядеть следующим образом:

 b = "0O000RAN0000GE"
  

Какой может быть наилучший способ решить эту проблему в Python? Возможно ли привязать индекс к каждой замене?

Большое спасибо! Хельга

Ответ №1:

Множество ответов / способов сделать это. В моем используется фундаментальное предположение, что ваше число в 1s равно длине слова, которое вы заменяете.

 a = "01000111000011"
a = a.replace("1", "%s")
b = "ORANGE"
print a % tuple(b)
  

Или строку pythonic 1 😉

 print "01000111000011".replace("1", "%s") % tuple("ORANGE")
  

Ответ №2:

 a = '01000111000011'
for char in 'ORANGE':
  a = a.replace('1', char, 1)
  

Или:

 b = iter('ORANGE')
a = ''.join(next(b) if i == '1' else i for i in '01000111000011')
  

Или:

 import re
a = re.sub('1', lambda x, b=iter('ORANGE'): b.next(), '01000111000011')
  

Комментарии:

1. Первая часть этого ответа, хотя и понятна, имеет ужасную производительность. Его не следует использовать, если эту задачу необходимо выполнить для более чем одной строки.

2. Вторая часть этого ответа будет иметь проблемы, если в исходной строке больше единиц, чем в символах замены (попробуйте решение с ‘01000111000011010101010101’).

Ответ №3:

 s_iter = iter("ORANGE")
"".join(next(s_iter) if c == "1" else c for c in "01000111000011")
  

Комментарии:

1. У этого ответа возникнут проблемы, если в исходной строке больше единиц, чем в символах замены (попробуйте решение с ‘01000111000011010101010101’).

Ответ №4:

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

 def helper(source, replacement):
    i = 0
    for c in source:
        if c == '1' and i < len(replacement):
            yield replacement[i]
            i  = 1
        else:
            yield c

a = '010001110001101010101'
b = 'ORANGE'
a = ''.join(helper(a, b)) # => '0O000RAN000GE01010101'
  

Ответ №5:

Улучшение решения bluepnume:

 >>> from itertools import chain, repeat
>>> b = chain('ORANGE', repeat(None))
>>> a = ''.join((next(b) or c) if c == '1' else c for c in '010001110000110101')
>>> a
'0O000RAN0000GE0101'
  

[ПРАВИТЬ]

Или еще проще:

 >>> from itertools import chain, repeat
>>> b = chain('ORANGE', repeat('1'))
>>> a = ''.join(next(b) if c == '1' else c for c in '010001110000110101')
>>> a
'0O000RAN0000GE0101'
  

[РЕДАКТИРОВАТЬ] #2

Также это работает:

 import re
>>> r = 'ORANGE'
>>> s = '010001110000110101'
>>> re.sub('1', lambda _,c=iter(r):next(c), s, len(r))
'0O000RAN0000GE0101'