在另一个字符串中计算多个字符串出现的次数

4
在Python 2.7中,给定以下字符串:
Spot is a brown dog. Spot has brown hair. The hair of Spot is brown.
最好的方法是找到字符串中“Spot”、“brown”和“hair”的总数。在这个例子中,它将返回8。
我想要像string.count("Spot","brown","hair")这样的东西,但是可以使用元组或列表中的“要查找的字符串”。
谢谢!

你想在单词"hairy"中计算出现次数为"hair"的次数吗?nltk的答案不会计算它,而count()和正则表达式的答案会。 - Eric O. Lebigot
通过添加单词边界(\b),使用 regex 轻松排除该问题。 - mgilson
确实如此,但这会改变你的答案。 :) - Eric O. Lebigot
目前,我的“要查找的字符串”已经足够复杂,不会像那样出现多个匹配项,但我感谢所有正则表达式信息和提示,以防我将来不得不回来。这也有助于未来的谷歌搜索者:D - DharmaTurtle
2个回答

13

这做了你要求的事情,但请注意它还会计算像“毛茸茸的”,“更棕色的”等单词。

>>> s = "Spot is a brown dog. Spot has brown hair. The hair of Spot is brown."
>>> sum(s.count(x) for x in ("Spot", "brown", "hair"))
8
你也可以将它写成一个map
>>> sum(map(s.count, ("Spot", "brown", "hair")))
8

更健壮的解决方案可能会使用nltk包

>>> import nltk  # Natural Language Toolkit
>>> from collections import Counter
>>> sum(x in {"Spot", "brown", "hair"} for x in nltk.wordpunct_tokenize(s))
8

我不打算对nltk发表任何意见,因为我不了解那个包 - 如果可以的话,我会再次+1支持它。 - mgilson
+1 对于nltk选项,它不会将“hairy”中的“hair”计入统计——如果这是原帖作者想要的。 - Eric O. Lebigot
nltk选项的速度渐近地比count()更快,因为它只读取一次输入字符串,并且由于成员资格测试在常数时间内完成。 - Eric O. Lebigot
如何获取每个短语(例如“绿色斑点”,“长棕色尾巴”,“红色头发”等)的唯一计数,并在表格中显示结果? - Leo Jones

4

我可能会使用一个计数器

s = 'Spot is a brown dog. Spot has brown hair. The hair of Spot is brown.'
words_we_want = ("Spot","brown","hair")
from collections import Counter
data = Counter(s.split())
print (sum(data[word] for word in words_we_want))

请注意,这将少计算1个,因为"brown."和"brown"是不同的计数器条目。
一个稍微不那么优雅的解决方案,不会在标点符号上出错,使用正则表达式:
>>> len(re.findall('Spot|brown|hair','Spot is a brown dog. Spot has brown hair. The hair of Spot is brown.'))
8

您可以通过简单地将元组中的内容创建为正则表达式来实现。
'|'.join(re.escape(x) for x in words_we_want)

这些解决方案的好处在于它们与gnibbler的解决方案相比具有更好的算法复杂度。当然,哪个解决方案在实际数据上表现更好仍需要由OP测量(因为OP是唯一拥有实际数据的人)。

1
我想,使用正则表达式,您可以通过 re.finditer 和老套路的 sum(1 for _ in ...) 习语来懒惰地评估它。 - mgilson
+1 对于 finditer() 和正则表达式总体来说是非常好的选择:它们在处理更大的字符串和可能的单词数量时速度很快。 - Eric O. Lebigot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接