给出一个输入列表(假设它们只是整数)和一个函数列表(这些函数采用整数,并返回True或False)。
我必须获取此输入列表,并查看列表中的任何函数是否会为列表中的任何值返回True。
有没有办法比O(n ^ 2)
更快地完成这项工作现在我拥有的是
for v in values:
for f in functions:
if f(v):
# do something to v
break
任何更快的方法?
答案 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 space为O(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是一个完全不同的故事,但在处理函数列表时,我倾向于用函数术语来思考。