用Python连接前后句子
我正在尝试把一组句子连接在一起,这些句子保存在一个 list
里。我有一个函数可以判断一个句子是否值得保存。不过,为了保持句子的上下文,我还需要保留它前面的句子和后面的句子。如果是边界情况,比如第一个句子或最后一个句子,我就只保留这个句子和它唯一的邻居。
举个例子比较好:
ex_paragraph = ['The quick brown fox jumps over the fence.',
'Where there is another red fox.',
'They run off together.',
'They live hapily ever after.']
t1 = lambda x: x.startswith('Where')
t2 = lambda x: x'startswith('The ')
对于 t1,结果应该是:
['The quick brown fox jumps over the fence. Where there is another red fox. They run off together.']
对于 t2,结果应该是:
['The quick brown fox jumps over the fence. Where there is another red fox.']
我的解决方案是:
def YieldContext(sent_list, cont_fun):
def JoinSent(sent_list, ind):
if ind == 0:
return sent_list[ind]+sent_list[ind+1]
elif ind == len(sent_list)-1:
return sent_list[ind-1]+sent_list[ind]
else:
return ' '.join(sent_list[ind-1:ind+1])
for sent, sentnum in izip(sent_list, count(0)):
if cont_fun(sent):
yield JoinSent(sent_list, sent_num)
有没有人知道更“干净”或者更符合 Python 风格的方法来做这样的事情?这个 if-elif-else
看起来有点勉强。
谢谢,
Will
PS. 我显然是在用一个更复杂的“上下文函数”,但这只是一个简单的例子。
4 个回答
1
我可能会这样做:
from itertools import izip, tee
prev, this, next = tee([''] + ex_paragraph + [''], 3)
this.next()
next.next()
next.next()
[' '.join(ctx).strip() for ctx in izip(prev, this, next) if cont_fun(this)]
这里的 cont_fun
可以是 t1
或者 t2
其中之一。
1
好吧,我可能只会把条件语句写成一行:
def join_send(sent_list, ind):
items = [sent_list[i] for i in (ind-1, ind, ind+1) if i >= 0 and i < len(sent_list)]
return ' '.join(items)
不过,这样写可能有人会觉得不太好读。
附言:更符合Python风格的写法应该是用PEP 8的命名方式,比如说yield_context。或者在某些库里,yieldContext也是可以的……但是YieldContext就有点奇怪了?
4
在列表的开头和结尾加一个空字符串其实是个不错的主意,但其实没必要用那些复杂的列表推导式。你可以很简单地创建一个生成器:
def yieldContext(l, func):
l = [''] + l + ['']
for i, s in enumerate(l):
if func(s):
yield ' '.join(l[i-1:i+2]).strip()
这样会得到:
>>> print list(yieldContext(ex_paragraph, t1))
['The quick brown fox jumps over the fence. Where there is another red fox. They run off together.']
>>> print list(yieldContext(ex_paragraph, t2))
['The quick brown fox jumps over the fence. Where there is another red fox.']
(如果你真的想创建一个列表,其实差别不大。主要还是看你有多少句子,以及你想怎么处理这些“上下文”)
def yieldContext(l, func):
l = [''] + l + ['']
return [' '.join(l[i-1:i+2]).strip() for i, s in enumerate(l) if func(s)]