在Python中使用map()获取列表元素在字符串中出现的次数
我正在尝试在Python中计算一个列表中每个项目在一个字符串中出现的次数:
paragraph = "I eat bananas and a banana"
def tester(x): return len(re.findall(x,paragraph))
map(tester, ['banana', 'loganberry', 'passion fruit'])
返回的结果是 [2, 0, 0]
不过,我想把这个功能扩展一下,让我可以把段落的内容传入map()函数。目前,tester()函数里面的段落是写死的。有没有人知道怎么做到这一点(也许可以创建一个包含多个段落值的列表)?还有其他的想法吗?
请记住,未来每个数组中的值都会有一个权重,所以需要把这些值保存在一个列表中,而不是把它们全部合在一起。
更新:这个段落的内容通常会有2万字,而列表里通常会有200多个成员。我在想,map函数是并行运行的,所以它会比任何串行的方法更高效。
7 个回答
3
targets = ['banana', 'loganberry', 'passion fruit']
paragraph = "I eat bananas and a banana"
print [paragraph.count(target) for target in targets]
我不知道你为什么在这里要用map()这个东西。
8
闭包可以是一个快速的解决方案:
paragraph = "I eat bananas and a banana"
def tester(s):
def f(x):
return len(re.findall(x,s))
return f
print map(tester(paragraph), ['banana', 'loganberry', 'passion fruit'])
1
这是对“我可能需要正则表达式,因为我将来可能需要单词分隔符”的回应:
这个方法只需解析文本一次,就能得到所有“单词”的列表。然后,每个单词都会在目标单词的字典中查找,如果是目标单词,就会被计数。这个过程的时间复杂度是 O(P) + O(T),其中 P 是段落的大小,T 是目标单词的数量。到目前为止,除了我的 Aho-Corasick 方法,其他所有解决方案(包括现在被接受的解决方案)都是 O(PT)。
def counts_all(targets, paragraph, word_regex=r"\w+"):
tally = dict((target, 0) for target in targets)
for word in re.findall(word_regex, paragraph):
if word in tally:
tally[word] += 1
return [tally[target] for target in targets]
def counts_iter(targets, paragraph, word_regex=r"\w+"):
tally = dict((target, 0) for target in targets)
for matchobj in re.finditer(word_regex, paragraph):
word = matchobj.group()
if word in tally:
tally[word] += 1
return [tally[target] for target in targets]
finditer 版本就像是一个不切实际的例子——它比 findall 版本慢得多。
这是目前被接受的解决方案,用标准化的形式表示,并增加了单词分隔符:
def currently_accepted_solution_augmented(targets, paragraph):
def tester(s):
def f(x):
return len(re.findall(r"\b" + x + r"\b", s))
return f
return map(tester(paragraph), targets)
这个方案在闭包的使用上有点过头,可以简化为:
# acknowledgement:
# this is structurally the same as one of hughdbrown's benchmark functions
def currently_accepted_solution_augmented_without_extra_closure(targets, paragraph):
def tester(x):
return len(re.findall(r"\b" + x + r"\b", paragraph))
return map(tester, targets)
目前被接受的解决方案的所有变种都是 O(PT)。与现在被接受的解决方案不同,带有单词分隔符的正则搜索并不等同于简单的 paragraph.find(target)
。因为在这种情况下,正则引擎并没有使用“快速搜索”,所以添加单词分隔符会让它从慢变得非常慢。