我想实现以下功能:
f(x) = a0 -inf < x < b0
a1 b0 <= x < b1
a2 b1 <= x < b2
...
an bn-1 <= x < bn
an+1 bn <= x < +inf
而不是普通的if-else实现。
def func(x):
if x<b0: return a0
elif x<b1: return a1
.....
我是否有更好的数据结构来组织此活动?
此外,在给定两个序列{an},{bn}的情况下,我如何编写一个返回优化的'func(x)'的'元函数'。
答案 0 :(得分:2)
如果n
大,则要减少if
条语句的数量。在Python中,这可以通过将数据存储在字典中来完成:
fx = {b0: a0, b1: a1, b2: a2, ..., bn: an, math.inf: an+1}
对于给定的x
值,对字典的键值进行二进制搜索。这为您提供了适当的键来使用,然后使用字典本身来获取相关值。如果您的语言不允许inf
作为键,则可以将an+1
的值与字典分开,也许将二者都保留为2元组。
这将最大测试次数从n
减少到log2(n)
。
在Python中,“元函数”很容易,因为函数是Python中的一类对象。您没有说明首选的语言:请告诉我您是否需要Python中的“元函数”示例。
答案 1 :(得分:0)
您可以仅存储a和b的数组。然后,要查找值,可以在b
数组中进行二进制搜索,以找到要返回到a
数组中的值的索引。
这实际上执行得很好,但是当我不得不为这个词法分析包(https://github.com/mtimmerm/dfalex)实现状态机时,我想出了一种更快的方法来完成此任务,我认为这很酷。
函数的表示形式是按顺序存储在数组中的二叉树,就像我们通常对堆所做的:https://www.geeksforgeeks.org/array-representation-of-binary-heap/
树的根在array[0]
中,任何array[i]
的左子节点在array[2i+1]
,而array[i]
的右子节点在{{1} }。树的叶子依次是所有array[2i+2]
(结果)值,每对相邻的a
值对之间的内部节点是您切换时的a
(参数)值从一个到另一个。
数组中的堆树顺序确保所有b
值在末尾连续出现。
这种表示法的好处是您可以使用此函数查找适当的值,这比二进制搜索更简单,更快捷:
a
很抱歉,如果我在python语法上犯了一个错误-这不是我所熟知的语言。
如果您需要构造一个只接受输入值的函数,则可以构建数组表示形式,并调用一个使闭包如下的函数:
def lookup(x, array, num_internal_nodes)
i=0
while (i < num_internal_nodes):
i = i*2 + (1 if x<array[i] else 2)
return array[i]
首先要构建函数的数组表示形式,只需制作一个大小合适的数组(def makeF(array, num_internal_nodes):
def f(x):
return lookup(x, array, num_internal_nodes)
return f
),然后对树进行预遍历,并填充{{1 }}(叶)和num_internal_nodes*2+1
(内部)值。