搜索算法,但功能

时间:2012-05-24 13:00:18

标签: python algorithm

给出一个输入列表(假设它们只是整数)和一个函数列表(这些函数采用整数,并返回True或False)。

我必须获取此输入列表,并查看列表中的任何函数是否会为列表中的任何值返回True。

有没有办法比O(n ^ 2)

更快地完成这项工作

现在我拥有的是

for v in values:
    for f in functions:
        if f(v):
            # do something to v
            break

任何更快的方法?

5 个答案:

答案 0 :(得分:10)

如果没有关于函数的任何进一步信息,len(functions) * len(values)可能的函数调用的结果必须被认为是彼此独立的,所以没有比检查它们更快的方法。

你可以更简洁地写一点:

any(f(v) for v in values for f in functions)

内置函数any()也会像原始代码一样短路。

修改:事实证明,所需的等效项

all(any(f(v) for f in functions) for v in values)

请参阅讨论的评论。

答案 1 :(得分:3)

不,没有更快的方法。 O(m * n)是极限。如果你有关于这些功能的更多信息,你可能会击败它,但在一般情况下,没有。

答案 2 :(得分:2)

如果您对函数或值有更多了解,您可以执行常规搜索引擎所做的事情 - 对值列表应用某种索引,只需要一次传递。

编辑:

这是一种适用于此用例的any()方法。

for v in values:
    if any(f(v) for f in functions):
        #do something to v

答案 3 :(得分:2)

只有通过查询它们并且对手头的函数没有一些简化的假设,你才能比O(nm)做得更好。

这是因为证明没有任何此类函数需要您证明,对于任何整数和任何函数,查询的结果都是False

为了证明这一点,您执行所有查询的效果都不尽如人意,因为state spaceO(2^nm)且查询只是将状态空间减半,因此您需要O(log_2(2^nm)) = O(nm)个查询来减少你的状态空间到解决方案“每个函数对每个整数都返回false”。

答案 4 :(得分:1)

这实际上不是O(n),但它可以避免每次迭代函数:

#combine all funcs into one with `or`
newFunc = reduce(lambda f,g: (lambda x: f(x) or g(x)), funcs)

#cleaner than for, i think
satisfied = any(map(newFunc, values))

讨论嵌套的lambdas是否是pythonic是一个完全不同的故事,但在处理函数列表时,我倾向于用函数术语来思考。