给定大小的值范围内的组合 [英] Combinations from range of values for given sizes

查看:59
本文介绍了给定大小的值范围内的组合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用以下代码为数组创建索引列表.但是,我希望索引以Fortran顺序运行,即内部循环是变化更快的循环.有没有一种方法可以在python中实现这一点.此刻,我得到的输出是C顺序.

I'm using the following code to create a list of indices for an array. However, I would like the index to run in Fortran order i.e. the inner loop being the faster varying loop. Is there a way to achieve this in python. At the moment, the output I get is in C order.

np.transpose(np.nonzero(np.ones([32,30])))

输出:

array([[ 0,  0],
       [ 0,  1],
       [ 0,  2],
       ..., 
       [31, 27],
       [31, 28],
       [31, 29]])

但是,我需要以下形式的输入:

However, I need the ouptut in the form:

array([[ 0,  0],
       [ 1,  0],
       [ 2,  0],
       ..., 
       [29, 29],
       [30, 29],
       [31, 29]])

推荐答案

A.两个参数解决方案(两列输出)

您可以使用np.indices生成这些索引,然后进行转置和整形-

A. Two param solution (two column output)

You could generate those indices with np.indices and then a transpose and a reshape does the job -

np.indices((32,30)).T.reshape(-1,2)

样本输出-

In [36]: np.indices((32,30)).T.reshape(-1,2)
Out[36]: 
array([[ 0,  0],
       [ 1,  0],
       [ 2,  0],
       ..., 
       [29, 29],
       [30, 29],
       [31, 29]])

运行时测试-

In [74]: points = [32,30]

# @218's soln
In [75]: %timeit np.transpose(np.nonzero(np.ones(points[::-1])))[:,::-1]
100000 loops, best of 3: 18.6 µs per loop

In [76]: %timeit np.indices((points)).T.reshape(-1,2)
100000 loops, best of 3: 16.1 µs per loop

In [77]: points = [320,300]

# @218's soln
In [78]: %timeit np.transpose(np.nonzero(np.ones(points[::-1])))[:,::-1]
100 loops, best of 3: 2.14 ms per loop

In [79]: %timeit np.indices((points)).T.reshape(-1,2)
1000 loops, best of 3: 1.26 ms per loop

进一步的性能提升

我们可以进一步优化它,方法是将翻转的pointsnp.indices结合使用,然后使用np.column_stack创建最终的2列数组.让我们花点时间,并对照已经提出的方案进行验证.在下面列出这两种方法-

We can optimize it further by using flipped points with np.indices and then using np.column_stack to create the final 2 columns array. Let's time and verify it against the already proposed one. Listing those two approaches below -

def app1(points):
    return np.indices((points)).T.reshape(-1,2)

def app2(points):
    R,C = np.indices((points[::-1]))
    return np.column_stack((C.ravel(), R.ravel()))

时间-

In [146]: points = [32,30]

In [147]: np.allclose(app1(points), app2(points))
Out[147]: True

In [148]: %timeit app1(points)
100000 loops, best of 3: 14.8 µs per loop

In [149]: %timeit app2(points)
100000 loops, best of 3: 17.4 µs per loop

In [150]: points = [320,300]

In [151]: %timeit app1(points)
1000 loops, best of 3: 1.1 ms per loop

In [152]: %timeit app2(points)
1000 loops, best of 3: 822 µs per loop

所以,这种形状在较大的形状上效果更好.

So, this one's better on bigger shapes.

我们将使其通用,以便我们可以使用给定的尽可能多的参数-

We will make it generic so that we could work with as many params as given, like so -

def get_combinations(params, order='right'):
    # params : tuple of input scalars that denotes sizes
    # The order arg is used for the LSB position. So, with order='right', the
    # rightmost column is the least significant, hence it will change the most
    # when going through the rows. For order='left', the leftmost column
    # would change the most.
    all_indices = np.indices(params)
    if order=='right':
        return np.moveaxis(all_indices,0,-1).reshape(-1,len(params))
    elif order=='left':
        return all_indices.T.reshape(-1,len(params))
    else:
        raise Exception('Wrong side value!')

示例案例-

In [189]: get_combinations((2,3), order='left')
Out[189]: 
array([[0, 0],
       [1, 0],
       [0, 1],
       [1, 1],
       [0, 2],
       [1, 2]])

In [191]: get_combinations((2,3,2), order='right')
Out[191]: 
array([[0, 0, 0],
       [0, 0, 1],
       [0, 1, 0],
       [0, 1, 1],
       [0, 2, 0],
       [0, 2, 1],
       [1, 0, 0],
       [1, 0, 1],
       [1, 1, 0],
       [1, 1, 1],
       [1, 2, 0],
       [1, 2, 1]])

这篇关于给定大小的值范围内的组合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆