разрезание строки Python со списком - PullRequest
4 голосов
/ 11 августа 2011

Вот мой список:

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).

Есть предложения?

Ответы [ 4 ]

5 голосов
/ 11 августа 2011

Предполагается, что 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)]
3 голосов
/ 11 августа 2011
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 голосов
/ 11 августа 2011

Вот одна компактная возможность:

"".join(s[i] for i in range(len(s)) if not any(start <= i <= end for start, end in liPos))
2 голосов
/ 11 августа 2011

Это ... быстрое решение проблемы. Возможно, есть и лучший способ, но это, по крайней мере, начало.

>>> 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!'
...