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

在python中,如果值在字典中匹配,则快速生成数组子集,python,numpy,dictionary,for-loop,Python,Numpy,Dictionary,For Loop,我正在努力加速这个功能。它检查字典中是否存在列表值的总和。例如,如果在添加[0,1]、[1,0]、[0,-1]和[-1,0]后,x所取的值存在于布局中,则将其作为输出中的一个选项删除。例如: 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]

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

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循环中运行了

风格 请不要说,例如,
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/COM>通常不会在一个MyFun调用和下一个MyFun调用之间发生变化,那么考虑将其作为一个参数传递到“代码>布局< /COD>”。顺便说一句,如果调用者愿意传入

x+可能性,您可以省略
x
参数


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

感谢您的富有洞察力的回答。当我运行O(1)解决方案时,我遇到了这样一个错误:unshable类型:“list”any ideas?列表是可变的,因此是不可修改的,因为如果内容发生变化,散列会发生变化。元组OTOH是不可变的,例如元组(i)是有效键,而列表(i)不是。