我正在尝试获取列表中每个项目的次数,位于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)
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top