您现在的位置是:首页 > 编程开发 > Python > Python

python – 使用设置重新排列for循环的顺序

编辑:站长来源:网络整理作者: 未知2020-12-20Python

简介我正在使用具有以下类型的结构/条目的数组(对于量子信息游戏中的主人项目); 第1列条目{0,1},第2列{0,第3列{0,2 **(d-1)},最后一列{0,d-1}. 如下d = 3: G = [[0 0 0 0] [0 0 0 1] [0 0 0 2] [0 0 1 0] [0 0 1 1] [0 0 1 2] [0 0 2 0] [0 0 2 1] [0 0 2 2] [0

我正在使用具有以下类型的结构/条目的数组(对于量子信息游戏中的主人项目);
第1列条目{0,1},第2列{0,第3列{0,2 **(d-1)},最后一列{0,d-1}.
如下d = 3:

G = 
[[0 0 0 0]
 [0 0 0 1]
 [0 0 0 2]
 [0 0 1 0]
 [0 0 1 1]
 [0 0 1 2]
 [0 0 2 0]
 [0 0 2 1]
 [0 0 2 2]
 [0 0 3 0]
 [0 0 3 1]
 [0 0 3 2]
 [0 1 0 0]
 [0 1 0 1]
 [0 1 0 2]
 [0 1 1 0]
 [0 1 1 1]
 [0 1 1 2]
 [0 1 2 0]
 [0 1 2 1]
 [0 1 2 2]
 [0 1 3 0]
 [0 1 3 1]
 [0 1 3 2]
 [1 0 0 0]
 [1 0 0 1]
 [1 0 0 2]
 [1 0 1 0]
 [1 0 1 1]
 [1 0 1 2]
 [1 0 2 0]
 [1 0 2 1]
 [1 0 2 2]
 [1 0 3 0]
 [1 0 3 1]
 [1 0 3 2]
 [1 1 0 0]
 [1 1 0 1]
 [1 1 0 2]
 [1 1 1 0]
 [1 1 1 1]
 [1 1 1 2]
 [1 1 2 0]
 [1 1 2 1]
 [1 1 2 2]
 [1 1 3 0]
 [1 1 3 1]
 [1 1 3 2]]

我正在使用以下函数来构建此数组:

def games(d = 3):
    res = np.empty(0).astype(int)
    for a in range(2):
        for b in range(2):
            for x in range(2**(d-1)):
                for y in range(d):
                    res = np.append(res,[a,b,x,y],axis=0)
    res = np.reshape(res,(-1,4))    
    return res

现在我想做的是,可以轻松选择列中的条目开始计数的顺序. (从左侧的右侧列开始.)

例如,假设Id像第一列开始计数,然后是第3列,然后是第4列,最后是第2列.我可以通过置换函数中的for循环来获得这个:

def games(d = 3):
    res = np.empty(0).astype(int)

    for b in range(2):
        for y in range(d):        
            for x in range(2**(d-1)):
                for a in range(2):
                    res = np.append(res,4))    
    return res

这使:

G=
[[0 0 0 0]
 [1 0 0 0]
 [0 0 1 0]
 [1 0 1 0]
 [0 0 2 0]
 [1 0 2 0]
 [0 0 3 0]
 [1 0 3 0]
 [0 0 0 1]
 [1 0 0 1]
 [0 0 1 1]
 [1 0 1 1]
 [0 0 2 1]
 [1 0 2 1]
 [0 0 3 1]
 [1 0 3 1]
 [0 0 0 2]
 [1 0 0 2]
 [0 0 1 2]
 [1 0 1 2]
 [0 0 2 2]
 [1 0 2 2]
 [0 0 3 2]
 [1 0 3 2]
 [0 1 0 0]
 [1 1 0 0]
 [0 1 1 0]
 [1 1 1 0]
 [0 1 2 0]
 [1 1 2 0]
 [0 1 3 0]
 [1 1 3 0]
 [0 1 0 1]
 [1 1 0 1]
 [0 1 1 1]
 [1 1 1 1]
 [0 1 2 1]
 [1 1 2 1]
 [0 1 3 1]
 [1 1 3 1]
 [0 1 0 2]
 [1 1 0 2]
 [0 1 1 2]
 [1 1 1 2]
 [0 1 2 2]
 [1 1 2 2]
 [0 1 3 2]
 [1 1 3 2]]

在函数中置换for循环的顺序是有效的,但是我必须编写24种不同的情况来覆盖所有的排列.任何人都知道一般来说会有更好的解决方案/方法吗?

解决方法

你正在计算的东西被称为“笛卡尔积”,并且偶然需要来自标准库的 itertools module具有在没有所有显式循环的情况下构造它的功能.通过置换给itertools.product的参数的顺序,确定列计数顺序.剩下要做的唯一事情是将列重新排列回所需的顺序,但这可以通过Numpy轻松完成.

import itertools

def make_games(d=3,perm=[3,2,1,0]):
    entries = [range(2),range(2),range(2**(d-1)),range(d)]
    # Python3 compatibility
    entries = [list(entry) for entry in entries]

    # Cartesian product with columns count-order by `perm`
    permuted_entries = [entries[px] for px in perm[::-1]]
    games_list = list(itertools.product(*permuted_entries))

    # Move the columns around to the original ordering
    sorter = np.argsort(perm[::-1])
    games = np.take(games_list,sorter,axis=1)

    return games

现在可以通过调用make_games(3,[0,3,1])来获得作为示例给出的输出.此外,现在可以通过循环遍历itertools.permutations(范围(4))轻松获得所有可能的排列.

作为奖励,这里有一种方法可以让Numpy(对于更大的d)更快地执行此操作:

def make_games_np(d=3,range(d)]
    # Python3 compatability
    entries = [list(entry) for entry in entries]

    n = len(entries)
    entries_grid = np.array(np.meshgrid(*entries,indexing='ij'))
    entries_grid = np.rollaxis(entries_grid,n+1)

    order = list(perm)[::-1] + [n]
    games = entries_grid.transpose(*order).reshape(-1,n)

    return games

很赞哦! ()

点击排行

本栏推荐

猜你喜欢