Python:如何在给定索引列表的字符串中替换子字符串

Den*_*gin 6 python string

我有一个字符串:

"A XYZ B XYZ C"
Run Code Online (Sandbox Code Playgroud)

和索引元组列表:

((2, 5), (8, 11))
Run Code Online (Sandbox Code Playgroud)

我想应用索引定义的每个子字符串替换它们的总和:

A 7 B 19 C
Run Code Online (Sandbox Code Playgroud)

我无法使用字符串替换,因为它将匹配XYZ的两个实例.随着索引在整个过程中转移,使用索引信息替换将在第二次和第四次迭代时中断.

这个问题有一个很好的解决方案吗?

UPDATE.例如,给出了字符串.我不是先验地知道它的内容,也不能在解决方案中使用它们.

我的脏解决方案是:

text = "A XYZ B XYZ C"
replace_list = ((2, 5), (8, 11))

offset = 0
for rpl in replace_list:
    l = rpl[0] + offset
    r = rpl[1] + offset

    replacement = str(r + l)
    text = text[0:l] + replacement + text[r:]

    offset += len(replacement) - (r - l)
Run Code Online (Sandbox Code Playgroud)

这取决于索引元组的升序顺序.可以做得更好吗?

Mik*_*ler 8

势在必行和有状态:

s = 'A XYZ B XYZ C'
indices = ((2, 5), (8, 11))
res = []
i = 0
for start, end in indices:
    res.append(s[i:start] + str(start + end))
    i = end
res.append(s[end:])
print(''.join(res))
Run Code Online (Sandbox Code Playgroud)

结果:

A 7 B 19 C
Run Code Online (Sandbox Code Playgroud)


Kas*_*mvd 5

你可以使用re.sub():

In [17]: s = "A XYZ B XYZ C"

In [18]: ind = ((2, 5), (8, 11))

In [19]: inds = map(sum, ind)

In [20]: re.sub(r'XYZ', lambda _: str(next(inds)), s)
Out[20]: 'A 7 B 19 C'
Run Code Online (Sandbox Code Playgroud)

但请注意,如果匹配数大于索引对,则会引发StopIteration错误.在这种情况下,您可以将默认参数传递给next()要替换子字符串.

如果你想使用索引元组来查找子字符串,这是另一种解决方案:

In [81]: flat_ind = tuple(i for sub in ind for i in sub)
# Create all the pairs with respect to your intended indices. 
In [82]: inds = [(0, ind[0][0]), *zip(flat_ind, flat_ind[1:]), (ind[-1][-1], len(s))]
# replace the respective slice of the string with sum of indices of they exist in intended pairs, otherwise just the sub-string itself.
In [85]: ''.join([str(i+j) if (i, j) in ind else s[i:j] for i, j in inds])
Out[85]: 'A 7 B 19 C'
Run Code Online (Sandbox Code Playgroud)


aso*_*uin 2

这是一个使用字符串格式化和元组解包的快速但有点脏的解决方案:

s = 'A XYZ B XYZ C'
reps = ((2, 5), (8, 11))
totals = (sum(r) for r in reps)
print s.replace('XYZ','{}').format(*totals)
Run Code Online (Sandbox Code Playgroud)

这打印:

A 7 B 19 C
Run Code Online (Sandbox Code Playgroud)

首先,我们使用生成器表达式来查找每个替换的总数。然后,通过替换'XYZ''{}',我们可以使用字符串格式-*totals将确保我们以正确的顺序获得总计。

编辑

我没有意识到索引实际上是字符串索引 - 我的错。为此,我们可以使用re.sub如下方法:

import re
s = 'A XYZ B XYZ C'

reps = ((2, 5), (8, 11))
for a, b in reps:
    s = s[:a] + '~'*(b-a) + s[b:]
totals = (sum(r) for r in reps)
print re.sub(r'(~+)', r'{}', s).format(*totals)
Run Code Online (Sandbox Code Playgroud)

假设您的字符串中没有~使用波浪号 ( ) - 如果有,请替换为其他字符。这还假设没有一个“替换”组是连续的。