数字のリストから長さn
のすべての組み合わせを取得する方法があるかどうか疑問に思いました。
たとえば、リストが[1, 2, 3, 4]
で、出力したい場合(n = 3を選択した場合)
[1, 2, 3]
[1, 2, 4]
[1, 3, 4]
[2, 3, 4]
[2,1,3]のような他の順列は私には役に立たない。
itertools これを行うことができます
import itertools
for comb in itertools.combinations([1, 2, 3, 4], 3):
print comb
出力
(1, 2, 3)
(1, 2, 4)
(1, 3, 4)
(2, 3, 4)
再帰関数の追加:
def combinations(array, Tuple_length, prev_array=[]):
if len(prev_array) == Tuple_length:
return [prev_array]
combs = []
for i, val in enumerate(array):
prev_array_extended = prev_array.copy()
prev_array_extended.append(val)
combs += combinations(array[i+1:], Tuple_length, prev_array_extended)
return combs
combinations([1, 2, 3, 4], 3)
出力:
[[1, 2, 3],
[1, 2, 4],
[1, 3, 4],
[2, 3, 4]]
すべての組み合わせを一度に計算したくない場合は、次のように長さnの組み合わせを返すジェネレーターを作成できます。
_def combinations(list_get_comb, length_combination):
""" Generator to get all the combinations of some length of the elements of a list.
:param list_get_comb: (list) List from which it is wanted to get the combination of its elements.
:param length_combination: (int) Length of the combinations of the elements of list_get_comb.
:return:
* :generator: Generator with the combinations of this list.
"""
# Generator to get the combinations of the indices of the list
def get_indices_combinations(sub_list_indices, max_index):
""" Generator that returns the combinations of the indices
:param sub_list_indices: (list) Sub-list from which to generate ALL the possible combinations.
:param max_index: (int) Maximum index.
:return:
"""
if len(sub_list_indices) == 1: # Last index of the list of indices
for index in range(sub_list_indices[0], max_index + 1):
yield [index]
Elif all([sub_list_indices[-i - 1] == max_index - i for i in
range(len(sub_list_indices))]): # The current sublist has reached the end
yield sub_list_indices
else:
for comb in get_indices_combinations(sub_list_indices[1:],
max_index): # Get all the possible combinations of the sublist sub_list_indices[1:]
yield [sub_list_indices[0]] + comb
# Advance one position and check all possible combinations
new_sub_list = []
new_sub_list.extend([sub_list_indices[0] + i + 1 for i in range(len(sub_list_indices))])
for new_comb in get_indices_combinations(new_sub_list, max_index):
yield new_comb # Return all the possible combinations of the new list
# Start the algorithm:
sub_list_indices = list(range(length_combination))
for list_indices in get_indices_combinations(sub_list_indices, len(list_get_comb) - 1):
yield [list_get_comb[i] for i in list_indices]
_
電話で:
_comb = combinations([1, 2, 3, 4], 3)
_
next(comb)
を呼び出すか、ループでジェネレーターを使用することにより、長さ3の可能な組み合わせを1つずつ計算できます:_for c in comb:
_。
このコードの利点は、リストが非常に長い場合、多くの可能な組み合わせがあり、いくつかの基準を満たすすべての可能な組み合わせの1つを取得したい場合、すべての可能な組み合わせを計算する必要がないことです。その基準でそれらをフィルタリングします。基準を満たす組み合わせが見つかるまで、1つずつ生成することができます。これにより、計算効率が大幅に向上します。また、上記のコードでは、可能なすべての組み合わせを計算してから長さでフィルタリングするのではなく、長さnの組み合わせのみを計算するため、効率も向上することに注意してください。
ただし、必要に応じて、list(comb)
をリストすることにより、すべての組み合わせを一度に計算できます。