我有以下相当简单的代码段:
def delete_substring_blocks(s, blocks):
'''
s: original input string
blocks: list of indices (start, end) to be deleted
return string `out` where blocks are deleted from s
'''
out = ''
p = 0
for start, end in blocks:
out += s[p:start]
p = end
out += s[p:]
return out
此函数采用字符串s
并删除s[start:end]
中的所有s
,其中索引(start, end)
对在列表blocks
中给出。
是否有某个内置函数可以执行相同的操作?
更新: 我的代码中有一个假设:
list.sort()
就地完成)至于块是否可以重叠,在我的用例中我确保它们在调用函数之前不会。但为了好玩,我们也可以假设他们这样做。
答案 0 :(得分:3)
我的方法将blocks
转换为一组我称之为exclude
的索引。之后,循环遍历字符串并排除索引在exclude
集中的那些字符。我使用set而不是list,因为它很好地处理重复项(如果重叠范围)。
exclude
集给定一个无序的,可能重叠的范围列表:
blocks = [(5, 7), (2, 4), (6, 10)]
我想将其转换为:
exclude = {2, 3, 5, 6, 7, 8, 9}
如何:
exclude = set()
for block in blocks:
exclude.update(range(*block))
这是我的代码和最后的一个小例子。请注意,我选择重命名该函数,因为此函数足够通用,可以处理字符串,列表,元组和其他可迭代对象,而不仅仅是字符串。另外,因为函数返回一个列表,所以当处理字符串时,我们需要将字符列表重新加入。
def delete_blocks(iterable, blocks):
exclude = set()
for block in blocks:
exclude.update(range(*block))
return [cell for i, cell in enumerate(iterable) if i not in exclude]
# Try it out
test_string = '0123456789abc'
blocks = [(5, 7), (2, 4), (6, 10)]
result = ''.join(delete_blocks(test_string, blocks))
print('Before: {!r}'.format(test_string))
print('Blocks:', blocks)
print('After: {!r}'.format(result))
delete_substring_blocks
为了真正回答Mai的问题,我使用delete_substring_blocks
实施了delete_blocks
:
def delete_substring_blocks(s, blocks):
return ''.join(delete_blocks(s, blocks))
答案 1 :(得分:0)
您需要按反向排序顺序处理块,否则字符串的预期部分将更改位置,块索引将无效。
这将是:
def delete_substring_blocks(s, blocks):
'''
s: original input string
blocks: list of indices (start, end) to be deleted
return string `out` where blocks are deleted from orig_str
'''
for start, end in reversed(sorted(blocks)):
s = s[:start] + s[end:]
return s
答案 2 :(得分:0)
由于未指明,我们必须假设块列表可能包含重叠。
一个效率相对较低的表达式,但是处理重叠和非排序块的表达式是:
def delete_substring_blocks(s, blocks):
return ''.join(
[c for i, c in enumerate(s)
if not any(blk for blk in blocks
if i >= blk[0] and i < blk[1])])
在这里,我们只测试每个角色的位置,看它是否在任何一个区间内,如果不是,则接受它。
以下是重叠块的示例:
>>> delete_substring_blocks(
"hello there how are you",
[[0, 3], [7, 9], [7, 10]])
'lo te how are you'
由于你似乎发现这个表达不可读,所以在这里分解一下:
def delete_substring_blocks(s, blocks):
def check_pos(i):
return not any(1 for start, end in blocks
if i >= start and i < end)
return ''.join([c for i, c in enumerate(s)
if check_pos(i)])
答案 3 :(得分:0)
这是一个基于位图的解决方案。它可以处理重叠块:
def delete_substring_blocks(s, blocks):
# create a bitmap with False for characters to be deleted
preserve = [True] * len(s)
for i, j in blocks:
preserve[i:j] = False
result = []
for i, c in enumerate(s):
if preserve[i]:
result.append(c)
return ''.join(result)
答案 4 :(得分:-1)
没有。你要求的是相当具体的。如果你想指定你想要保留的字符串部分(而不是删除),你可以很容易地将它排成一行。
>>> string = 'my long string'
>>> ''.join([string[s:e] for s, e in [(0,3), (8, 14)]])
'my string'