Python 可逆笛卡尔积元素/索引转换函数

Python 可逆笛卡尔积元素/索引转换函数,python,numpy,itertools,Python,Numpy,Itertools,我有一个问题,我需要识别在索引位置中找到的元素 但也可以是相反的,即从一系列列表中元素的唯一组合中识别索引位置 我已经编写了以下代码,可以很好地执行任务: import numpy as np def index_from_combination(meta_list_shape, index_combination ): list_product = np.prod(meta_list_shape) m_factor = np.cumprod([[l] for e,l in e

我有一个问题,我需要识别在索引位置中找到的元素 但也可以是相反的,即从一系列列表中元素的唯一组合中识别索引位置

我已经编写了以下代码,可以很好地执行任务:

import numpy as np

def index_from_combination(meta_list_shape, index_combination ):
    list_product = np.prod(meta_list_shape)
    m_factor = np.cumprod([[l] for e,l in enumerate([1]+meta_list_shape)])[0:len(meta_list_shape)]
    return np.sum((index_combination)*m_factor,axis=None)


def combination_at_index(meta_list_shape, index ):
    il = len(meta_list_shape)-1
    list_product = np.prod(meta_list_shape)
    assert index < list_product
    m_factor = np.cumprod([[l] for e,l in enumerate([1]+meta_list_shape)])[0:len(meta_list_shape)][::-1]
    idxl = []
    for e,m in enumerate(m_factor):
        if m<=index:
            idxl.append((index//m))
            index = (index%m)
        else:
            idxl.append(0)
    return idxl[::-1]
其中
[3,2]
描述了一系列两个列表,一个包含3个元素,另一个包含2个元素。组合
[2,1]
表示由第一个列表中的第三个元素(零索引)和第二个列表中的第二个元素(再次零索引)组成的排列

…如果有点笨拙(为了节省空间,忽略列表的实际内容,而使用其他地方使用的索引从这些列表中获取内容,这在这里并不重要)

注意:重要的是我的职能相互反映,以便:

F(a)==b   and G(b)==a  
i、 它们是彼此的倒数

从链接的问题来看,我可以用一行替换第二个函数:

list(itertools.product(['A','B','C'],['P','Q','R'],['X','Y']))[index]
它将返回所提供的索引整数的唯一值组合(尽管在我的脑海中有一些问号,关于该列表中有多少是在内存中实例化的,但同样,现在这并不一定重要)


我要问的是,itertools似乎是在考虑这些类型的问题的情况下构建的-是否有一条与
itertools.product
函数同样简洁的直线相反,如果给定一个组合,例如
['a','Q','Y']
将返回一个描述该组合在笛卡尔乘积中位置的整数,这样,如果将该整数输入到
itertools.product
函数,它将返回原始组合?

将这些组合想象为二维X-Y坐标,并使用
下标进行线性索引转换,反之亦然。因此,使用NumPy的内置函数获取线性索引和下标索引,这将分别成为您的
index\u from\u composition
composition\u at\u index

这是一个简单的翻译,不会产生任何组合,所以应该是轻而易举的事

运行示例以使事情更清楚-

In [861]: np.ravel_multi_index((2,1),(3,2))
Out[861]: 5

In [862]: np.unravel_index(5, (3,2))
Out[862]: (2, 1)
如果出于某种原因不想计算依赖项,那么这个数学很简单,可以实现-

def index_from_combination(a, b):
    return b[0]*a[1] + b[1]

def combination_at_index(a, b):
    d = b//a[1]
    r = b - a[1]*d
    return d, r
样本运行-

In [881]: index_from_combination([3,2],[2,1])
Out[881]: 5

In [882]: combination_at_index([3,2],5)
Out[882]: (2, 1)

非常优雅的答案,并且已经测试了12个维度,我认为进一步扩展的潜力在概念上(如果不是实际上)是无限的-谢谢!有时候numpy既惊讶又高兴,这就是其中之一。同样感谢“香草”代码——我还没有掌握广播(?)在这个深度,现在就完全掌握它,但再一次,我喜欢优雅。谢谢。@TomKimber是的,如果你在2D数组中输入数据,每一行都是一个组合,那么NumPy funcs将进行广播。因此,它具有性能优势。
In [881]: index_from_combination([3,2],[2,1])
Out[881]: 5

In [882]: combination_at_index([3,2],5)
Out[882]: (2, 1)