2017-10-19 10 views
1

the Cartesian product of a series of listsのインデックス位置にある要素を特定する必要があるだけでなく、その逆数、つまり一連の要素の固有の組み合わせからのインデックス位置を特定する必要があるという問題がありますリストの。反転可能デカルト積分要素/インデックス変換関数

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]は、2つの一連のリストを記述する

index_from_combination([3,2],[2,1]) 
>> 5 
combination_at_index([3,2],5) 
>> [2,1] 

、3つの要素、及びその他を含む2つの要素を含むもの。組合せ[2,1]は、第1のリストからの第3の要素(ゼロインデックス付け)と、第2のリストからの第2の要素(再びゼロインデックス付け)とからなる置換を示す。

...もしかしたら、スペースを節約するために、リストの実際の内容を無視し、他の場所で使用されているインデックスを使ってそれらのリストから内容を取り出す - これは重要ではありません。

N.B.重要なのは、私の機能が次のように互いに鏡像であるということです:

F(a)==b and G(b)==a 

つまり、それらはお互いの逆です。リンク質問から

は、それは私がワンライナーと第2の機能を置き換えることができ判明:いくつかのquestion-にかかわらず、(付属のインデックス整数の値のユニークな組み合わせを返します
list(itertools.product(['A','B','C'],['P','Q','R'],['X','Y']))[index] 

そのリストのどれくらいがメモリ内でインスタンス化されているかについて私の心に留めておいてください - しかし、今でもそれは必ずしも重要ではありません)。

itertoolsは、これらのタイプの問題を念頭に置いて作成されているようです。itertools.product関数と同じようにきちんとした1行の逆関数があります。 ['A','Q','Y']は、この整数がitertools.product関数に入力された場合、元の組み合わせを返すように、デカルト積の中のその組み合わせの位置を表す整数を返しますか?

答えて

2

これらの組み合わせを2次元X-Y座標とし、subscript to linear-index conversionと副詞を使用するとします。したがって、NumPyの組み込み関数np.ravel_multi_indexを使用して線形インデックスを取得し、np.unravel_indexを添字インデックスに使用します。これはそれぞれindex_from_combinationcombination_at_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) 

あなたには、いくつかの理由でnumpyの依存関係にしたくない場合は、数学が実装されるのに十分に簡単です -

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) 
+0

すばらしくエレガント回答、及び12件の寸法にそれをテストした、私はさらに拡張の可能性は、Cであると仮定します知覚的に(事実上ではないにしても)無限に - ありがとう!時にはnumpyも驚きと歓喜の両方があり、これはその時代の一つです。 "バニラ"コードもありがとう - 私はまだこの深みで放送(?)を手に入れて、今は完全にそれを手に入れようとしていますが、再びエレガンスを愛しています。ありがとうございました。 –

+0

あなたは各行が組み合わせである2次元アレイ、フィード場合@TomKimberはい、numpyのののfuncsとが放送されるであろう。だから、パフォーマンス上の利点があります。 – Divakar

関連する問題