有效地填充具有许多if else语句的多维数组

时间:2016-10-15 18:59:58

标签: python arrays numpy

我希望以特定且有效的方式填充4dim numpy数组。因为我不知道更好,我开始用if else语句编写代码,但这看起来并不好看,可能很慢,我也不能确定我是否考虑过每一个组合。这是我停止写下的代码:

sercnew2 = numpy.zeros((gn, gn, gn, gn))
for x1 in range(gn):
    for x2 in range(gn):
        for x3 in range(gn):
            for x4 in range(gn):
                if x1 == x2 == x3 == x4: 
                    sercnew2[x1, x2, x3, x4] = ewp[x1]
                elif x1 == x2 == x3 != x4:
                    sercnew2[x1, x2, x3, x4] = ewp[x1] * ewp[x4]
                elif x1 == x2 == x4 != x3:
                    sercnew2[x1, x2, x3, x4] = ewp[x1] * ewp[x3]
                elif x1 == x3 == x4 != x2:
                    sercnew2[x1, x2, x3, x4] = ewp[x1] * ewp[x2]
                elif x2 == x3 == x4 != x1:
                    sercnew2[x1, x2, x3, x4] = ewp[x2] * ewp[x1]
                elif x1 == x2 != x3 == x4:
                    sercnew2[x1, x2, x3, x4] = ewp[x1] * ewp[x3]
                elif ... many more combinations which have to be considered

基本上应该发生的是,如果所有变量(x1,x2,x3,x4)彼此不同,则条目为:

sercnew2[x1, x2, x3, x4] = ewp[x1]* ewp[x2] * ewp[x3] * ewp[x4]

现在,如果我们说变量x2和x4是相同的那么:

sercnew2[x1, x2, x3, x4] = ewp[x1]* ewp[x2] * ewp[x3]

其他例子可以在上面的代码中看到。基本上如果两个或多个变量相同,那么我只考虑它们。我希望这种模式很清楚。否则请让我注意,我会尝试更好地表达我的问题。我很确定,有一种更聪明的方法可以做到这一点。希望你知道更好,并提前感谢:)

3 个答案:

答案 0 :(得分:3)

我真的不知道你的意思是说这些变量是相同的,但如果确实如此,那么你只需要使用set()

from functools import reduce
from operator import mul
sercnew2 = numpy.zeros((gn, gn, gn, gn))
for x1 in range(gn):
    for x2 in range(x1, gn):
        for x3 in range(x2, gn):
            for x4 in range(x3, gn):
                set_ = [ewp[n] for n in set([x1, x2, x3, x4])]
                sercnew2[x1, x2, x3, x4] = reduce(mul, set_, 1)

它的工作方式是创建一个删除重复项的set(),稍后使用reduce函数从set_中选择第一个数字,将其与1相乘(初始值设定值),其结果将作为第一个参数传递给reduce,第二个将是set_的第二个项目。对不起我的错误解释。

答案 1 :(得分:3)

真的希望我能得到它!这是一个矢量化方法 -

if(count($routeArray) != count($requestArray)) {
    return FALSE; // the route does not match
}

for($i = 0 ; $i < count($routeArray) ; $i++)
{
     if($routeArray[$i][0] != '{' && $routeArray[$i] != $requestArray[$i]) {
         return FALSE; // the route does not match
     }
}

return TRUE; // still here? route matches!

答案 2 :(得分:2)

您也可以在单个for循环中执行此操作。在Divakar的Trick上建立索引列表,我们要做的第一件事是弄清楚如何只提取4d数组sercnew2中给定元素的唯一索引。

执行此操作的最快方法之一(参考:https://www.peterbe.com/plog/uniqifiers-benchmark)正在使用集合。然后,我们只需将sercnew2初始化为1的数组,而不是零。

from itertools import product
import numpy as np

sercnew2 = np.ones((gn, gn, gn, gn))
n_dims=4
idx = list(product(np.arange(gn), repeat=n_dims))

for i,j,k,l in idx:
    unique_items = set((i,j,k,l))
    for ele in unique_items:
        sercnew2[i,j,k,l] *= ewp[ele]
编辑:正如@unutbu建议的那样,我们也可以使用https://stackoverflow.com/a/11146645/5714445中的cartesian_product函数来加速idx的初始化

编辑2:如果您无法理解来自product的{​​{1}}内容,它会提供所有排列。例如,假设itertools,重复维度设置为4,则得到

gn=2