목록 요소의 가능한 모든 조합을 얻는 방법은 무엇입니까?
나는 15 개의 숫자가있는 목록을 가지고 있으며 그 숫자의 32,768 조합을 모두 생성하는 코드를 작성해야합니다.
내가 찾고있는 것을 분명히하는 일부 코드 (구글링)를 찾았지만 코드가 상당히 불투명하고 코드를 사용하는 것에주의를 기울였습니다. 또한 더 우아한 솔루션이 있어야한다고 생각합니다.
나에게 발생하는 유일한 일은 십진 정수 1-32768을 반복하여 이진수로 변환하고 이진 표현을 필터로 사용하여 적절한 숫자를 선택하는 것입니다.
누구든지 더 나은 방법을 알고 있습니까? 사용 map()
, 아마?
itertools.combinations를 살펴보십시오 .
itertools.combinations(iterable, r)
입력 iterable에서 요소의 r 길이 하위 시퀀스를 반환합니다.
조합은 사전 식 정렬 순서로 방출됩니다. 따라서 입력 반복 가능 항목이 정렬되면 조합 튜플이 정렬 된 순서로 생성됩니다.
2.6부터 배터리가 포함되어 있습니다!
이 답변 은 한 가지 측면을 놓쳤습니다. OP는 길이 "r"의 조합뿐만 아니라 모든 조합을 요구했습니다.
따라서 모든 길이 "L"을 반복해야합니다.
import itertools
stuff = [1, 2, 3]
for L in range(0, len(stuff)+1):
for subset in itertools.combinations(stuff, L):
print(subset)
또는-만약 당신이 멋지게하려면 (또는 당신의 코드를 읽는 사람의 두뇌를 구부리려면) "combinations ()"생성기 체인을 생성하고 그것을 통해 반복 할 수 있습니다 :
from itertools import chain, combinations
def all_subsets(ss):
return chain(*map(lambda x: combinations(ss, x), range(0, len(ss)+1)))
for subset in all_subsets(stuff):
print(subset)
itertools를 사용하는 게으른 원 라이너가 있습니다.
from itertools import compress, product
def combinations(items):
return ( set(compress(items,mask)) for mask in product(*[[0,1]]*len(items)) )
# alternative: ...in product([0,1], repeat=len(items)) )
이 답변의 기본 개념은 길이가 N 인 이진 문자열의 수와 동일한 2 ^ N 조합입니다. 각 이진 문자열에 대해 "1"에 해당하는 모든 요소를 선택합니다.
items=abc * mask=###
|
V
000 ->
001 -> c
010 -> b
011 -> bc
100 -> a
101 -> a c
110 -> ab
111 -> abc
고려해야 할 사항 :
- 이것은 당신이 호출 할 수 있어야
len(...)
에items
(다음과 같은 경우 해결items
발전기와 같은 반복 가능한 같은 것입니다, 먼저 목록으로 바꿀items=list(_itemsArg)
) - 이를 위해서는 반복 순서
items
가 무작위가 아니어야합니다 (해결 방법 : 제정신이 아닙니다). - 이 항목은 고유의, 또는 다른 것을 요구
{2,2,1}
하고{2,1,1}
에 모두 붕괴 할 것이다{2,1}
(: 사용 해결collections.Counter
드롭 인 교체 등을set
, 나중에 사용해야 할 수도 있지만이 ... 기본적으로 MULTISET의tuple(sorted(Counter(...).elements()))
당신이 해쉬 할 필요하면)
데모
>>> list(combinations(range(4)))
[set(), {3}, {2}, {2, 3}, {1}, {1, 3}, {1, 2}, {1, 2, 3}, {0}, {0, 3}, {0, 2}, {0, 2, 3}, {0, 1}, {0, 1, 3}, {0, 1, 2}, {0, 1, 2, 3}]
>>> list(combinations('abcd'))
[set(), {'d'}, {'c'}, {'c', 'd'}, {'b'}, {'b', 'd'}, {'c', 'b'}, {'c', 'b', 'd'}, {'a'}, {'a', 'd'}, {'a', 'c'}, {'a', 'c', 'd'}, {'a', 'b'}, {'a', 'b', 'd'}, {'a', 'c', 'b'}, {'a', 'c', 'b', 'd'}]
@Dan H 의 높은지지를받은 답변 아래, Dan 자신을 포함한 문서 의 powerset()
레시피에 대한 언급이 있습니다. 그러나 지금까지 아무도 답변으로 게시하지 않았습니다. 아마도 문제에 대한 최선의 접근 방법이 아니라면 더 나은 방법 중 하나 일 수 있으며 다른 의견 자가 약간의 격려 를 받으면 아래에 나와 있습니다. 이 함수는 가능한 모든 길이 의 목록 요소 (0 및 모든 요소를 포함하는 요소 포함)의 고유 한 모든 조합을 생성 합니다 .itertools
참고 : 미묘하게 다른 목표가 고유 한 요소의 조합 만 얻는 것이라면 행 s = list(iterable)
을 변경하여 s = list(set(iterable))
중복 요소를 제거하십시오. 그럼에도 불구하고 iterable
궁극적으로 list
이것이 다른 여러 답변과 달리 발전기와 함께 작동 하는 수단 으로 바뀐다는 사실 .
from itertools import chain, combinations
def powerset(iterable):
"powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
s = list(iterable) # allows duplicate elements
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
stuff = [1, 2, 3]
for i, combo in enumerate(powerset(stuff), 1):
print('combo #{}: {}'.format(i, combo))
산출:
combo #1: ()
combo #2: (1,)
combo #3: (2,)
combo #4: (3,)
combo #5: (1, 2)
combo #6: (1, 3)
combo #7: (2, 3)
combo #8: (1, 2, 3)
다음은 재귀를 사용하는 것입니다.
>>> import copy
>>> def combinations(target,data):
... for i in range(len(data)):
... new_target = copy.copy(target)
... new_data = copy.copy(data)
... new_target.append(data[i])
... new_data = data[i+1:]
... print new_target
... combinations(new_target,
... new_data)
...
...
>>> target = []
>>> data = ['a','b','c','d']
>>>
>>> combinations(target,data)
['a']
['a', 'b']
['a', 'b', 'c']
['a', 'b', 'c', 'd']
['a', 'b', 'd']
['a', 'c']
['a', 'c', 'd']
['a', 'd']
['b']
['b', 'c']
['b', 'c', 'd']
['b', 'd']
['c']
['c', 'd']
['d']
이 원 라이너는 모든 조합 ( 원래 목록 / 세트에 고유 한 요소 가 포함 된 경우 항목 0
과 n
항목 사이 n
)을 제공하고 기본 방법을 사용합니다 itertools.combinations
.
파이썬 2
from itertools import combinations
input = ['a', 'b', 'c', 'd']
output = sum([map(list, combinations(input, i)) for i in range(len(input) + 1)], [])
파이썬 3
from itertools import combinations
input = ['a', 'b', 'c', 'd']
output = sum([list(map(list, combinations(input, i))) for i in range(len(input) + 1)], [])
출력은 다음과 같습니다.
[[],
['a'],
['b'],
['c'],
['d'],
['a', 'b'],
['a', 'c'],
['a', 'd'],
['b', 'c'],
['b', 'd'],
['c', 'd'],
['a', 'b', 'c'],
['a', 'b', 'd'],
['a', 'c', 'd'],
['b', 'c', 'd'],
['a', 'b', 'c', 'd']]
온라인으로 사용해보십시오 :
본인은 Ben이 실제로 모든 조합을 요청한 Dan H에 동의합니다 . itertools.combinations()
모든 조합을 제공하지는 않습니다.
또 다른 문제는 입력 iterable이 큰 경우 목록의 모든 것 대신 생성기를 반환하는 것이 좋습니다.
iterable = range(10)
for s in xrange(len(iterable)+1):
for comb in itertools.combinations(iterable, s):
yield comb
이 간단한 코드를 사용하여 파이썬에서 목록의 모든 조합을 생성 할 수 있습니다
import itertools
a = [1,2,3,4]
for i in xrange(0,len(a)+1):
print list(itertools.combinations(a,i))
결과는 다음과 같습니다.
[()]
[(1,), (2,), (3,), (4,)]
[(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]
[(1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]
[(1, 2, 3, 4)]
itertools 또는 다른 추가 라이브러리를 가져 오지 않고 답변을 원하는 사람들을 위해이 기능을 추가 할 것이라고 생각했습니다.
def powerSet(items):
"""
Power set generator: get all possible combinations of a list’s elements
Input:
items is a list
Output:
returns 2**n combination lists one at a time using a generator
Reference: edx.org 6.00.2x Lecture 2 - Decision Trees and dynamic programming
"""
N = len(items)
# enumerate the 2**N possible combinations
for i in range(2**N):
combo = []
for j in range(N):
# test bit jth of integer i
if (i >> j) % 2 == 1:
combo.append(items[j])
yield combo
간단한 수율 생성기 사용법 :
for i in powerSet([1,2,3,4]):
print (i, ", ", end="")
위 사용 예의 출력 :
[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3], [4], [1, 4] , [2, 4], [1, 2, 4], [3, 4], [1, 3, 4], [2, 3, 4], [1, 2, 3, 4],
이것은 재귀를 지원하는 모든 프로그래밍 언어 (itertools, yield, list comprehension)없이 쉽게 전달할 수있는 접근 방식입니다 .
def combs(a):
if len(a) == 0:
return [[]]
cs = []
for c in combs(a[1:]):
cs += [c, c+[a[0]]]
return cs
>>> combs([1,2,3,4,5])
[[], [1], [2], [2, 1], [3], [3, 1], [3, 2], ..., [5, 4, 3, 2, 1]]
여기에 itertools.combinations
함수 를 사용하는 또 다른 솔루션 (한 줄짜리)이 있지만 여기서는 for 루프 또는 합계와 달리 이중 목록 이해를 사용합니다.
def combs(x):
return [c for i in range(len(x)+1) for c in combinations(x,i)]
데모:
>>> combs([1,2,3,4])
[(),
(1,), (2,), (3,), (4,),
(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4),
(1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4),
(1, 2, 3, 4)]
itertools를 사용하여 수행 할 수 있습니다
순열
이 메소드는리스트를 입력으로 받아서 길이 L의 순열을리스트 형식으로 포함하는 튜플의 오브젝트리스트를 리턴합니다.
# A Python program to print all
# permutations of given length
from itertools import permutations
# Get all permutations of length 2
# and length 2
perm = permutations([1, 2, 3], 2)
# Print the obtained permutations
for i in list(perm):
print (i)
조합
이 메소드는리스트와 입력 r을 입력으로 받아서 길이 r의 가능한 모든 조합을리스트 형식으로 포함하는 튜플의 오브젝트리스트를 리턴합니다.
# A Python program to print all
# combinations of given length
from itertools import combinations
# Get all combinations of [1, 2, 3]
# and length 2
comb = combinations([1, 2, 3], 2)
# Print the obtained combinations
for i in list(comb):
print (i)
볼 이
아래는 다른 유사한 답변 https://stackoverflow.com/a/23743696/711085 와 유사한 "표준 재귀 답변" 입니다. (N! 순열을 모두 처리 할 수있는 방법이 없기 때문에 실제로 스택 공간 부족에 대해 걱정할 필요가 없습니다.)
모든 요소를 차례로 방문하여 가져 오거나 떠납니다 (이 알고리즘에서 2 ^ N 카디널리티를 직접 볼 수 있음).
def combs(xs, i=0):
if i==len(xs):
yield ()
return
for c in combs(xs,i+1):
yield c
yield c+(xs[i],)
데모:
>>> list( combs(range(5)) )
[(), (0,), (1,), (1, 0), (2,), (2, 0), (2, 1), (2, 1, 0), (3,), (3, 0), (3, 1), (3, 1, 0), (3, 2), (3, 2, 0), (3, 2, 1), (3, 2, 1, 0), (4,), (4, 0), (4, 1), (4, 1, 0), (4, 2), (4, 2, 0), (4, 2, 1), (4, 2, 1, 0), (4, 3), (4, 3, 0), (4, 3, 1), (4, 3, 1, 0), (4, 3, 2), (4, 3, 2, 0), (4, 3, 2, 1), (4, 3, 2, 1, 0)]
>>> list(sorted( combs(range(5)), key=len))
[(),
(0,), (1,), (2,), (3,), (4,),
(1, 0), (2, 0), (2, 1), (3, 0), (3, 1), (3, 2), (4, 0), (4, 1), (4, 2), (4, 3),
(2, 1, 0), (3, 1, 0), (3, 2, 0), (3, 2, 1), (4, 1, 0), (4, 2, 0), (4, 2, 1), (4, 3, 0), (4, 3, 1), (4, 3, 2),
(3, 2, 1, 0), (4, 2, 1, 0), (4, 3, 1, 0), (4, 3, 2, 0), (4, 3, 2, 1),
(4, 3, 2, 1, 0)]
>>> len(set(combs(range(5))))
32
목록 이해 사용하기 :
def selfCombine( list2Combine, length ):
listCombined = str( ['list2Combine[i' + str( i ) + ']' for i in range( length )] ).replace( "'", '' ) \
+ 'for i0 in range(len( list2Combine ) )'
if length > 1:
listCombined += str( [' for i' + str( i ) + ' in range( i' + str( i - 1 ) + ', len( list2Combine ) )' for i in range( 1, length )] )\
.replace( "', '", ' ' )\
.replace( "['", '' )\
.replace( "']", '' )
listCombined = '[' + listCombined + ']'
listCombined = eval( listCombined )
return listCombined
list2Combine = ['A', 'B', 'C']
listCombined = selfCombine( list2Combine, 2 )
결과는 다음과 같습니다.
['A', 'A']
['A', 'B']
['A', 'C']
['B', 'B']
['B', 'C']
['C', 'C']
이 코드는 중첩 목록이있는 간단한 알고리즘을 사용합니다.
# FUNCTION getCombos: To generate all combos of an input list, consider the following sets of nested lists...
#
# [ [ [] ] ]
# [ [ [] ], [ [A] ] ]
# [ [ [] ], [ [A],[B] ], [ [A,B] ] ]
# [ [ [] ], [ [A],[B],[C] ], [ [A,B],[A,C],[B,C] ], [ [A,B,C] ] ]
# [ [ [] ], [ [A],[B],[C],[D] ], [ [A,B],[A,C],[B,C],[A,D],[B,D],[C,D] ], [ [A,B,C],[A,B,D],[A,C,D],[B,C,D] ], [ [A,B,C,D] ] ]
#
# There is a set of lists for each number of items that will occur in a combo (including an empty set).
# For each additional item, begin at the back of the list by adding an empty list, then taking the set of
# lists in the previous column (e.g., in the last list, for sets of 3 items you take the existing set of
# 3-item lists and append to it additional lists created by appending the item (4) to the lists in the
# next smallest item count set. In this case, for the three sets of 2-items in the previous list. Repeat
# for each set of lists back to the initial list containing just the empty list.
#
def getCombos(listIn = ['A','B','C','D','E','F'] ):
listCombos = [ [ [] ] ] # list of lists of combos, seeded with a list containing only the empty list
listSimple = [] # list to contain the final returned list of items (e.g., characters)
for item in listIn:
listCombos.append([]) # append an emtpy list to the end for each new item added
for index in xrange(len(listCombos)-1, 0, -1): # set the index range to work through the list
for listPrev in listCombos[index-1]: # retrieve the lists from the previous column
listCur = listPrev[:] # create a new temporary list object to update
listCur.append(item) # add the item to the previous list to make it current
listCombos[index].append(listCur) # list length and append it to the current list
itemCombo = '' # Create a str to concatenate list items into a str
for item in listCur: # concatenate the members of the lists to create
itemCombo += item # create a string of items
listSimple.append(itemCombo) # add to the final output list
return [listSimple, listCombos]
# END getCombos()
itertools를 사용하여 모든 조합 을 얻는 것이 훨씬 실용적이라는 것을 알고 있지만 원하는 경우 많은 코드를 작성하려는 경우 목록 이해 만으로이 부분을 달성 할 수 있습니다
두 쌍의 조합 :
lambda l: [(a, b) for i, a in enumerate(l) for b in l[i+1:]]
그리고 세 쌍의 조합의 경우 다음과 같이 쉽습니다.
lambda l: [(a, b, c) for i, a in enumerate(l) for ii, b in enumerate(l[i+1:]) for c in l[i+ii+2:]]
결과는 itertools.combinations를 사용하는 것과 같습니다.
import itertools
combs_3 = lambda l: [
(a, b, c) for i, a in enumerate(l)
for ii, b in enumerate(l[i+1:])
for c in l[i+ii+2:]
]
data = ((1, 2), 5, "a", None)
print("A:", list(itertools.combinations(data, 3)))
print("B:", combs_3(data))
# A: [((1, 2), 5, 'a'), ((1, 2), 5, None), ((1, 2), 'a', None), (5, 'a', None)]
# B: [((1, 2), 5, 'a'), ((1, 2), 5, None), ((1, 2), 'a', None), (5, 'a', None)]
itertools를 사용하지 않고 :
def combine(inp):
return combine_helper(inp, [], [])
def combine_helper(inp, temp, ans):
for i in range(len(inp)):
current = inp[i]
remaining = inp[i + 1:]
temp.append(current)
ans.append(tuple(temp))
combine_helper(remaining, temp, ans)
temp.pop()
return ans
print(combine(['a', 'b', 'c', 'd']))
다음은 두 가지 구현입니다. itertools.combinations
리스트를 돌려주는 것
def combinations(lst, depth, start=0, items=[]):
if depth <= 0:
return [items]
out = []
for i in range(start, len(lst)):
out += combinations(lst, depth - 1, i + 1, items + [lst[i]])
return out
하나는 발전기를 반환
def combinations(lst, depth, start=0, prepend=[]):
if depth <= 0:
yield prepend
else:
for i in range(start, len(lst)):
for c in combinations(lst, depth - 1, i + 1, prepend + [lst[i]]):
yield c
prepend 인수는 정적이며 모든 호출에서 변경되지 않으므로 도우미 기능을 제공하는 것이 좋습니다.
print([c for c in combinations([1, 2, 3, 4], 3)])
# [[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]
# get a hold of prepend
prepend = [c for c in combinations([], -1)][0]
prepend.append(None)
print([c for c in combinations([1, 2, 3, 4], 3)])
# [[None, 1, 2, 3], [None, 1, 2, 4], [None, 1, 3, 4], [None, 2, 3, 4]]
이것은 매우 피상적이지만 미안보다 안전합니다.
어떻습니까 ..리스트 대신 문자열을 사용했지만 같은 것은 .. 문자열은 파이썬에서리스트처럼 취급 될 수 있습니다.
def comb(s, res):
if not s: return
res.add(s)
for i in range(0, len(s)):
t = s[0:i] + s[i + 1:]
comb(t, res)
res = set()
comb('game', res)
print(res)
itertools의 조합
import itertools
col_names = ["aa","bb", "cc", "dd"]
all_combinations = itertools.chain(*[itertools.combinations(col_names,i+1) for i,_ in enumerate(col_names)])
print(list(all_combinations))
감사
itertools
Python 3이 없으면 다음과 같이 할 수 있습니다.
def combinations(arr, carry):
for i in range(len(arr)):
yield carry + arr[i]
yield from combinations(arr[i + 1:], carry + arr[i])
처음에는 carry = "".
이것은 내 구현입니다
def get_combinations(list_of_things):
"""gets every combination of things in a list returned as a list of lists
Should be read : add all combinations of a certain size to the end of a list for every possible size in the
the list_of_things.
"""
list_of_combinations = [list(combinations_of_a_certain_size)
for possible_size_of_combinations in range(1, len(list_of_things))
for combinations_of_a_certain_size in itertools.combinations(list_of_things,
possible_size_of_combinations)]
return list_of_combinations
def combinations(iterable, r):
# combinations('ABCD', 2) --> AB AC AD BC BD CD
# combinations(range(4), 3) --> 012 013 023 123
pool = tuple(iterable)
n = len(pool)
if r > n:
return
indices = range(r)
yield tuple(pool[i] for i in indices)
while True:
for i in reversed(range(r)):
if indices[i] != i + n - r:
break
else:
return
indices[i] += 1
for j in range(i+1, r):
indices[j] = indices[j-1] + 1
yield tuple(pool[i] for i in indices)
x = [2, 3, 4, 5, 1, 6, 4, 7, 8, 3, 9]
for i in combinations(x, 2):
print i
누군가가 반대로 목록을 찾고 있다면 :
stuff = [1, 2, 3, 4]
def reverse(bla, y):
for subset in itertools.combinations(bla, len(bla)-y):
print list(subset)
if y != len(bla):
y += 1
reverse(bla, y)
reverse(stuff, 1)
flag = 0
requiredCals =12
from itertools import chain, combinations
def powerset(iterable):
s = list(iterable) # allows duplicate elements
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
stuff = [2,9,5,1,6]
for i, combo in enumerate(powerset(stuff), 1):
if(len(combo)>0):
#print(combo , sum(combo))
if(sum(combo)== requiredCals):
flag = 1
break
if(flag==1):
print('True')
else:
print('else')
참고 URL : https://stackoverflow.com/questions/464864/how-to-get-all-possible-combinations-of-a-list-s-elements
'Programming' 카테고리의 다른 글
UIButton에 여러 줄 텍스트를 어떻게 추가합니까? (0) | 2020.02.29 |
---|---|
Android Studio : / dev / kvm 기기 권한이 거부되었습니다. (0) | 2020.02.29 |
Enum 값을 문자열 리터럴로 사용 (0) | 2020.02.29 |
암호에 대한 정규식은 8 자 이상, 하나 이상의 숫자 및 소문자와 특수 문자를 모두 포함해야합니다. (0) | 2020.02.29 |
ArrayList를 문자열로 변환하는 가장 좋은 방법 (0) | 2020.02.29 |