使用map()获取python中的字符串中存在列表元素的次数
题
我正在尝试获取列表中每个项目的次数,位于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()函数的段落为硬编码。是否有人有办法做到这一点(也许是n-Length段落值列表)?这里还有其他想法吗?
请记住,每个数组值将来都会有一个重量 - 因此需要将值保留在列表中,而不是将它们全部处理在一起。
更新:段落通常为20K,列表通常会有200多个成员。我的想法是地图并行运行 - 因此,它将比任何串行方法都要高得多。
解决方案
以下是对球门柱运动的回应(“我可能需要正则是正则是,因为我在不久的将来需要单词定界符”):
此方法一次解析文本,以获取所有“单词”的列表。每个单词都在目标词的字典中查找,如果是目标词,则计算出来。所需的时间为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)。与当前接受的解决方案不同,带有Word定界符的正则搜索不等于一个简单的 paragraph.find(target)
. 。因为在这种情况下,RE引擎不使用“快速搜索”,所以添加单词的定界符将其更慢地更改为 非常 减缓。
其他提示
关闭将是一个快速解决方案:
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'])
targets = ['banana', 'loganberry', 'passion fruit']
paragraph = "I eat bananas and a banana"
print [paragraph.count(target) for target in targets]
不知道为什么您会在此处使用Map()。
我知道您没有要求列表理解,但是无论如何是:
paragraph = "I eat bananas and a banana"
words = ['banana', 'loganberry', 'passion fruit']
[len(re.findall(word, paragraph)) for word in words]
这也返回[2,0,0]。
基本上,这只是您避免列表理解的竭尽全力,但是如果您喜欢功能风格的编程,那么您会喜欢 Functools.partial.
>>> from functools import partial
>>> def counter(text, paragraph):
return len(re.findall(text, paragraph))
>>> tester = partial(counter, paragraph="I eat bananas and a banana")
>>> map(tester, ['banana', 'loganberry', 'passion fruit'])
[2, 0, 0]
对于Q查询平均长度l字节的平均长度字节,大小为t字节的大字节,您需要的东西不是O(QLT)。您需要一种DFA风格的方法,可以在设置成本后为您提供O(t)。如果您的查询集相当静态,则可以忽略设置成本。
例如 http://en.wikipedia.org/wiki/Aho-Corasick_algorithm
这指向Python的C延伸:
http://hkn.eecs.berkeley.edu/~dyoo/python/ahocorasick/
这是我的版本。
paragraph = "I eat bananas and a banana"
def tester(paragraph, x): return len(re.findall(x,paragraph))
print lambda paragraph: map(
lambda x: tester(paragraph, x) , ['banana', 'loganberry', 'passion fruit']
)(paragraph)