0

指定されたリストの可能な製品の方法を見つけたいと思います。基本的に、インデックスの後には、A1A2、A2C3 ... または循環番号 A3D1、D3B1 ... などのその番号の隣にある番号を続けることができます。以下に例を示します。

例:

the_list=['A1','A2','A3','B1','B2','B3','C1','C2','C3','D1','D2','D3']
The results should be: 
['A1A2','A1B2','A1C2','A1D2','A2A3','A2B3','A2C3','A2D3','A3A1','A3B1','A3C1','A3D1'
 'B1A2,'B2A3'...
 'C1A2'...']

これまでのところ、私はこれを試しました:

the_list=['A1','A2','A3','B1','B2','B3','C1','C2','C3','D1','D2','D3']
result=[]
for i in range(len(the_list)):
    for k in range((i%3+1),len(the_list)+1,3):
        s=str(the_list[i])+str(the_list[k%len(the_list)])
        result.append(s)

出力:

['A1A2', 'A1B2', 'A1C2', 'A1D2', 'A2A3', 'A2B3', 'A2C3', 'A2D3', 'A3B1', 'A3C1', 
    'A3D1', 'A3A1', 'B1A2', 'B1B2', 'B1C2', 'B1D2', 'B2A3', 'B2B3', 'B2C3', 'B2D3', 'B3B1', 
    'B3C1', 'B3D1', 'B3A1', 'C1A2', 'C1B2', 'C1C2', 'C1D2', 'C2A3', 'C2B3', 'C2C3', 'C2D3', 
    'C3B1', 'C3C1', 'C3D1', 'C3A1', 'D1A2', 'D1B2', 'D1C2', 'D1D2', 'D2A3', 'D2B3', 'D2C3', 
    'D2D3', 'D3B1', 'D3C1', 'D3D1', 'D3A1']

これはうまくいきます。しかし、よりスケーラブルにしたいのですが、これまでのところ、A1A2、A1D2 などの 2 つのシーケンスが生成されます...スケーラブルにするためにコードを変更するにはどうすればよいですか? したがって、スケールが 3 の場合、同じ方法で A1A2A3 を生成する必要があります。

更新:サイズを処理し、その数に基づいてシーケンスを累積する for ループがもう 1 つあるはずですが、これまでのところ方法がわかりませんでした。

4

5 に答える 5

1

これがあなたが求めているものだと思います。

import itertools

def products(letters='ABCD', N=3, scale=2):
    for lets in itertools.product(letters, repeat=scale):
        for j in xrange(N):
            yield ''.join('%s%d' % (c, (i + j) % N + 1)
                          for i, c in enumerate(lets))

print list(products(scale=3))
于 2013-01-05T21:40:45.377 に答える
1
  • numbers = IT.cycle(numbers)有効な数値のシーケンスを生成するために使用します。サイクルにすることで、1フォローとフォローを3別のものとして扱う必要がなくなり2ます1
  • 各項目の文字はitertools.productで生成できます。パラメータはここ repeatで特に役立ちます。あなたが言うように、追加の労力なしでジェネレーターをより長いシーケンスに「スケーリング」できます。
  • によって生成された文字(以下で呼び出されます) をfrom とzip組み合わせるために 使用できます。itertools.productletsnumbersitertools.cycle
  • ''.join(IT.chain.from_iterableによって返されたタプルのリストを文字列に結合する方法にすぎませzipん。

import itertools as IT

def neighbor_product(letters, numbers, repeat = 2):
    N = len(numbers)
    numbers = collections.deque(numbers)
    for lets in IT.product(letters, repeat = repeat):
        for i in range(N):
            yield ''.join(IT.chain.from_iterable(zip(lets, IT.cycle(numbers))))
            numbers.rotate(-1)

letters = 'ABCD'
numbers = '123'
for item in neighbor_product(letters, numbers, repeat = 3):
    print(item)

収量

A1A2A3
A2A3A1
A3A1A2
A1A2B3
...
D3D1C2
D1D2D3
D2D3D1
D3D1D2
于 2013-01-05T23:08:34.953 に答える
0

仕様に従ってすべての組み合わせが有効であるとは限らないため、考えられるすべての組み合わせをチェックして無効なものを破棄することは、ここでは最善の方法ではない可能性があります。

各アイテムの数は、組み合わせが有効かどうかを判断するために重要であるため、最初にそのためのルックアップ テーブルを作成しましょう。

from collections import defaultdict

lookup = defaultdict(list)
for item in the_list:
    lookup[int(item[1])].append(item)

これにより、特定の番号を持つすべてのアイテムを簡単に取得できます (これは、連続する番号のアイテムを取得する場合に役立ちます)。

lookup[1] == ['A1', 'B1', 'C1', 'D1']

すべての有効な組み合わせを作成するには、次のようにします。

from itertools import product

def valid_combinations(lookup):
    min_number = min(lookup)
    max_number = max(lookup)
    for number in lookup:
        # Let's just assume here that we've only got consecutive numbers, no gaps:
        next_number = min_number if number == max_number else number + 1
        for combination in product(lookup[number], lookup[next_number]):
            yield ''.join(combination)

任意の数のアイテムをチェーンできるようにするには、少し変更する必要があります。

def valid_combinations(lookup, scale = 2):
    min_number = min(lookup)
    max_number = max(lookup)
    def wrap_number(n):
        while n > max_number:
            n -= max_number + 1 - min_number
        return n
    for number in lookup:
        numbers = list(wrap_number(n) for n in range(number, number + scale))
        items = [lookup[n] for n in numbers]
        for combination in product(*items):
            yield ''.join(combination)

スケール 5 の場合、これにより次の結果が生成されます (合計 3072 の最初の数個のみを表示)。

['A1A2A3A1A2', 'A1A2A3A1B2', 'A1A2A3A1C2', 'A1A2A3A1D2', 'A1A2A3B1A2', ...]
于 2013-01-05T22:49:14.863 に答える
0

あなたが探しているのは、可能なすべての順列のサブセットだと思います。itertools.permutations()指定されたシーケンスと指定された長さ n の n サイズのタプルとして、すべての順列のジェネレータを返します。すべての順列を繰り返し処理し、基準に基づいてそれらをフィルタリングします。これはどうですか:

In [1]: from itertools import permutations

In [2]: the_list = ['A1','A2','A3','B1','B2','B3','C1','C2','C3','D1','D2','D3']

In [3]: results = []

In [4]: digits = list(set([elem[1] for elem in the_list]))

In [5]: digits
Out[5]: ['1', '2', '3']

In [6]: for perm in permutations(the_list, 2):
  ....:     if (int(perm[0][1])+1 == int(perm[1][1]) or 
  ....:        (perm[0][1] == digits[-1] and perm[1][1] == digits[0])): 
  ....:         results.append(''.join(perm))

In [7]: sorted(results)
Out[7]: ['A1A2', 'A1B2', 'A1C2', 'A1D2', 'A2A3', 'A2B3', 'A2C3', 
         'A2D3', 'A3A1', 'A3B1', 'A3C1', 'A3D1', 'B1A2', 'B1B2', 
         'B1C2', 'B1D2', 'B2A3', 'B2B3', 'B2C3', 'B2D3', 'B3A1', 
         'B3B1', 'B3C1', 'B3D1', 'C1A2', 'C1B2', 'C1C2', 'C1D2', 
         'C2A3', 'C2B3', 'C2C3', 'C2D3', 'C3A1', 'C3B1', 'C3C1', 
         'C3D1', 'D1A2', 'D1B2', 'D1C2', 'D1D2', 'D2A3', 'D2B3', 
         'D2C3', 'D2D3', 'D3A1', 'D3B1', 'D3C1', 'D3D1']
于 2013-01-05T21:38:50.640 に答える
0

result=[i+j for i for the_list in the_list]

于 2013-01-05T21:36:45.897 に答える