我有字符串,其中包含"Page 2"格式的页码。我想删除这些页码。
字符串可能是:
"第一个是第 10 页,然后是第1 页,然后是第 12 页">
当前实现:
有没有比下面更优雅的方法来删除所有"页面#{some_number}"?
page_numbers = [
'Page 1',
'Page 2',
'Page 3',
'Page 4',
'Page 5',
'Page 6',
'Page 7',
'Page 8',
'Page 9',
'Page 10',
'Page 11',
'Page 12']
x = "The first is Page 10 and then Page 1 and then Page 12"
for v in page_numbers:
x = x.replace(v, ' ')
print(x)
这应该可以做到,使用 re 模块:
>>> import re
>>> x = "The first is Page 10 and then Page 1 and then Page 12"
>>> re.sub(r'(s?Page d{1,3})', ' ', x)
'The first is and then and then '
re.sub
将正则表达式的所有匹配项替换为 x 上的第二个参数(替换字符串)(第三个参数)
那么,正则表达式在做什么呢?
s?
只是吃掉第 n 页文本之前的空格(如果它在那里)Page
与"Page "
字符串完全匹配(带空格)d{1,3}
匹配 1 到 3 位数字。如果您只能处理到 99,请使用d{1,2}
。如果您需要更多,只需调整即可。
re.sub
的答案是正确的,但不完整。如果您只想删除某些页码,那么仅靠一个简单的re.sub
解决方案是不够的。您需要提供回调才能使其正常工作。
p_set = set(page_numbers)
def replace(m):
p = m.group()
return ' ' if p in p_set else p
现在,将replace
作为回调传递给re.sub
-
>>> re.sub('Page d+', replace, x)
'The first is and then and then '
re.sub
的第二个参数接受回调,在找到匹配项时调用该回调。相应的match
对象作为参数传递给replace
,这应该返回一个替换值。
我还page_numbers
转换为set
.这使我在确定是保留还是丢弃匹配的字符串时,对p_set
执行恒定时间查找。
为了获得更大的灵活性,您可以支持删除某个范围内的页码 -
def replace(m):
return ' ' if int(m.group(1)) in range(1, 13) else m.group()
并恰当地称呼它——
>>> re.sub('Page (d+)', replace, x)
'The first is and then and then '
这比维护一个列表/一组页码更有效,假设您的删除范围是连续的。需要注意的另一件事是,使用in
运算符对range
对象进行成员资格检查在计算上是廉价的(常量时间)。
你可以像这样使用正则表达式来做到这一点:
import re
x ="The first is Page 10 and then Page 1 and then Page 12"
print(re.sub(r'Page d+', '', x))
这将查找所有"Page",后跟空格和任意数量的数字,并将其替换为任何内容。
如果您想在单词之间保持间距,请执行以下操作:
re.sub(r'Pagesd+s', '', x)
这将匹配后面的空格并替换它,因为如果没有,您将有 2 个空格(一个来自 Page 之前,一个来自它之后)