这是我的清单:
liPos = [(2,5),(8,9),(18,22)]
每个元组的第一项是起始位置,第二项是结束位置。 然后我有一个像这样的字符串:
s = "I hope that I will find an answer to my question!"
现在,考虑到我的liPos
列表,我想通过删除元组中提供的每个起始位置和结束位置(以及包括周围数字)之间的字符来格式化字符串。这是我想要的结果:
"I tt I will an answer to my question!"
所以基本上,我想删除2和5之间的字符(包括2和5),然后是8,9(包括8和9)之间的字符,最后是18,22(包括18和22)之间的字符。
有什么建议吗?
答案 0 :(得分:5)
这假设liPos
已经排序,如果sorted(liPos, reverse=True)
循环中未使用for
。
liPos = [(2,5),(8,9),(18,22)]
s = "I hope that I will find an answer to my question!"
for begin, end in reversed(liPos):
s = s[:begin] + s[end+1:]
print s
这是一个替代方法,它构造一个新的切片元组列表以包含,然后仅使用那些包含的部分连接字符串。
from itertools import chain, izip_longest
# second slice index needs to be increased by one, do that when creating liPos
liPos = [(a, b+1) for a, b in liPos]
result = "".join(s[b:e] for b, e in izip_longest(*[iter(chain([0], *liPos))]*2))
为了使这更容易理解,以下是izip_longest
生成的切片:
>>> list(izip_longest(*[iter(chain([0], *liPos))]*2))
[(0, 2), (6, 8), (10, 18), (23, None)]
答案 1 :(得分:3)
这是一个紧凑的可能性:
"".join(s[i] for i in range(len(s)) if not any(start <= i <= end for start, end in liPos))
答案 2 :(得分:3)
liPos = [(2,5),(8,9),(18,22)]
s = "I hope that I will find an answer to my question!"
exclusions = set().union(* (set(range(t[0], t[1]+1)) for t in liPos) )
pruned = ''.join(c for i,c in enumerate(s) if i not in exclusions)
print pruned
答案 3 :(得分:2)
这......快速解决了这个问题。可能有更好的方法,但这至少是一个开始。
>>> liPos = [(2,5),(8,9),(18,22)]
>>>
>>> toRemove = [i for x, y in liPos for i in range(x, y + 1)]
>>>
>>> toRemove
[2, 3, 4, 5, 8, 9, 18, 19, 20, 21, 22]
>>>
>>> s = "I hope that I will find an answer to my question!"
>>>
>>> s2 = ''.join([c for i, c in enumerate(s) if i not in toRemove])
>>>
>>> s2
'I tt I will an answer to my question!'