我不会建议使用您匹配的单词不同的定界符两边
它更容易(%
并在你的例子&
。)在标记的单词的任一侧使用相同的分隔符并使用Python的列表分片。
以下解决方案使用[::n]
语法获取列表中的每个n
个元素。
a[::2]
得到偶数编号的元素,a[1::2]
得到奇数。
>>> fox = "the|quick|brown|fox|jumpsoverthelazydog"
因为他们两边|
字符,'quick'
和'fox'
是奇数的元素,当你劈在|
字符串:
>>> splitfox = fox.split('|')
>>> splitfox
['the', 'quick', 'brown', 'fox', 'jumpsoverthelazydog']
>>> splitfox[1::2]
['quick', 'fox']
,其余均为偶数:
>>> splitfox[::2]
['the', 'brown', 'jumpsoverthelazydog']
因此,通过将|
字符中的已知单词括起来,分割并扫描even-nu复杂的元素,您只能搜索那些尚未匹配的文本部分。这意味着你在已经匹配的单词中不匹配。
from itertools import chain
def flatten(list_of_lists):
return chain.from_iterable(list_of_lists)
def parse(source_text, words):
words.sort(key=len, reverse=True)
texts = [source_text, ''] # even number of elements helps zip function
for word in words:
new_matches_and_text = []
for text in texts[::2]:
new_matches_and_text.append(text.replace(word, f"|{word}|"))
previously_matched = texts[1::2]
# merge new matches back in
merged = '|'.join(flatten(zip(new_matches_and_text, previously_matched)))
texts = merged.split('|')
# remove blank words (matches at start or end of a string)
texts = [text for text in texts if text]
return ' '.join(texts)
>>> parse('acatisananimal', ['cat', 'is', 'a', 'an', 'animal'])
'a cat is an animal'
>>> parse('atigerisanenormousscaryandbeautifulanimal', ['tiger', 'is', 'an', 'and', 'animal'])
'a tiger is an enormousscary and beautiful animal'
的merge
代码使用zip
和flatten
功能拼接的新比赛和老一起匹配。它基本上是通过将列表中的偶数和奇数元素进行配对来实现的,然后将结果“拼合”成一个长列表,为下一个单词做好准备。
该方法在文本中留下无法识别的单词。
'beautiful'
和'a'
处理得好,因为他们对自己的(即靠近识别的单词。)
'enormous'
和'scary'
不是已知的,因为他们是彼此相邻,他们离开粘在一起。
下面是如何列出未知的话:
>>> known_words = ['cat', 'is', 'an', 'animal']
>>> sentence = parse('anayeayeisananimal', known_words)
>>> [word for word in sentence.split(' ') if word not in known_words]
['ayeaye']
我很好奇:这是一个生物信息学项目?
你现在的输出是什么? –
@ t.m.adam嗯,我知道。但是,当我在评论的上下文中使用定义时,我问的是“最终”初始化_任何地方_。但是,是的,你完全正确。 –
[我的解决方案](http://stackoverflow.com/a/43366440/5811078)也适用于这种情况。 – zipa