如果值在python中的字典中匹配,则快速子集数组

时间:2017-09-05 03:01:26

标签: python numpy dictionary for-loop

我正在努力加快这项功能。它检查列表中是否存在列表值的总和。例如,如果在x中添加[0, 1][1, 0][0, -1][-1, 0]之后layout所需的值,则将其删除作为输出中的一个选项。例如:

layout = { 0:[2,1], 1:[3,1], 2:[2,2], 3:[6,3] }
x = [2, 1]

possibilities = numpy.zeros(shape=(4,2))
possibilities[0] = [1, 0]
possibilities[1] = [-1, 0]
possibilities[2] = [0, 1]
possibilities[3] = [0, -1]

def myFun(x, layout, possibilities):
    new_possibilities = possibilities + x

    output_direction = []
    for i in new_possibilities:
        i = list(i)
        output_direction.append( (i in layout.values()) )

    output_direction = true_to_false(output_direction)
    possibilities = possibilities[output_direction]
    if possibilities.size == 0:
        possibilities = [0, 0]
        return possibilities
    else:
        return possibilities

# This changes True to False
def true_to_false(y):
output = []
for i in y:
    if i == True:
         output.append((False))
    elif i == False:
        output.append((True))       
return output

如果我现在运行此功能,我会得到以下输出:

myFun(x, layout, possibilities)

array([[-1.,  0.],
       [ 0., -1.]])

我收到此输出的原因是因为[0, 0] + x在布局中被[2,1]占用,[0,1] + x在布局中被[2,2]占用,而[1,0] + x是在布局中由[3,1]占用,而布局中不存在[-1, 0] + x[0, -1] + x,因此这是输出结果。

这个函数运行正常,我希望它更快,因为布局可以变得非常大(成千上万的项目),并且这个函数已经在for循环中运行。

1 个答案:

答案 0 :(得分:1)

请注明print((((42))))时,请不要说print(42)。多余的括号使您的代码更难阅读。

否定

你的否定功能可以简化为:

def true_to_false(y):
    return [not b
            for b in y]

但你甚至不需要那样。您可以删除该功能,并在追加时使用not来避免功能调用的费用:

output_direction = []
for i in new_possibilities:
    output_direction.append(list(i) not in layout.values())
possibilities = possibilities[output_direction]
...

即便如此,也是在冗长的一面,因为它自然适合列表理解:

output_direction = [list(i) not in layout.values()
                    for i in new_possibilities]

速度

反复询问i是否在.values()范围内的问题是线性扫描。如果len(layout.values())变得非常大,那么您确实希望将这些值放入哈希映射中:

vals = set(layout.values())
output_direction = [list(i) not in vals
                    for i in new_possibilities]

现在O(n)线性扫描成为O(1)恒定时间哈希查找。

如果vals通常在一次myFun调用和下一次调用之间没有变化,那么请考虑将其作为参数与layout一起传递。顺便说一句,如果来电者愿意传递x,你可以忽略x + possibilities参数。

您是否考虑过使用集合交叉点?