This question already has answers here:
How to get all possible combinations of a list’s elements?
(32 answers)
Power set and Cartesian Product of a set python
(1 answer)
Closed 1 year ago.
So say you have n numbers in a list as so
[n1, n2, n3, ...., n]
How would you get all possible combinations?
For example if you had
[1,2,3,4]
You return a list like:
[[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]]
Here is a generator function, using the go-to itertools.combinations:
from itertools import combinations
def combos(lst):
for n in range(2, len(lst)+1):
yield from combinations(lst, n)
list(combos([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)]
If you desperately need lists instead of tuples:
list(map(list, combos([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]]
Related
This question already has answers here:
How to get the cartesian product of multiple lists
(17 answers)
Closed 2 years ago.
I have m-length list of tuples.
For example:
m = 2
mylist = [(1, 2), (3, 4)]
I need to get all combinations of these tuples, using only one element from one tuple:
[1, 3]
[1, 4]
[2, 3]
[2, 4]
For m=3:
mylist = [(1, 2), (3, 4), (5, 6)]
[1, 3, 5]
[1, 3, 6]
[1, 4, 5]
[1, 4, 6]
[2, 3, 5]
[2, 3, 6]
[2, 4, 5]
[2, 4, 6]
Is there any good way to do it for any m?
You can use itertools.product:
import itertools
for el in itertools.product(*mylist):
print(el)
Outputs:
(1, 3)
(1, 4)
(2, 3)
(2, 4)
Ref. https://docs.python.org/3/library/itertools.html#itertools.product
This question already has answers here:
How to generate list combinations?
(4 answers)
Closed 5 years ago.
I'm hoping that there's a 'Pythonic' way to do this. Let's say that I have a list and an integer.
foo = [1, 2]
bar = 2
I want to return a series of lists where each list is the length specified by the integer (or length -1), where the lists represent an expression of each possible combination of values in the list. So for instance, the output I'm looking for would be something like this:
>> [[1, 1], [1, 2], [2, 1], [2, 2]]
if bar was equal to three, then:
>> [[1, 1, 1], [1, 1, 2], [1, 2, 2], [2, 1, 2], [2, 2, 1], [1, 2, 1], [2, 1, 1], [2, 2, 2]]
... and so on.
>>> import itertools
>>> foo = [1,2]
>>> list(itertools.product(foo, repeat=2))
[(1, 1), (1, 2), (2, 1), (2, 2)]
>>> list(itertools.product(foo, repeat=3))
[(1, 1, 1), (1, 1, 2), (1, 2, 1), (1, 2, 2), (2, 1, 1), (2, 1, 2), (2, 2, 1), (2, 2, 2)]
>>>
I am doing a question based on combinations and just stuck in it. And yes I am not so good in python.
The itertools combinations function using ncr just return the r possible combinations from n. I want something which will return the r possible combinations selected and also the other remaining elements from n numbers which were not selected in that iteration.
Example:
>>>from itertools import combinations
>>>list = [1, 2, 3, 4, 5]
>>>rslt = combinations(list, 2)
when [2, 4] is selected it should also return [1, 3, 5]
so it should return like [[2, 4], [1, 3, 5]]
Thanks in advance
itertools.combinations
Return r length subsequences of elements from the input iterable.
You can use a list comprehension to get the other items [j for j in l if j not in i]:
from itertools import combinations
l = [1, 2, 3, 4, 5]
for i in combinations(l,2):
print(list(i),[j for j in l if j not in i])
And you will get :
[1, 2] [3, 4, 5]
[1, 3] [2, 4, 5]
[1, 4] [2, 3, 5]
[1, 5] [2, 3, 4]
[2, 3] [1, 4, 5]
[2, 4] [1, 3, 5]
[2, 5] [1, 3, 4]
[3, 4] [1, 2, 5]
[3, 5] [1, 2, 4]
[4, 5] [1, 2, 3]
By the way, it's not recommended to use list as a variable name.
The simplest way would be to make a copy of the original list, removing the elements that are in the combination:
from itertools import combinations
def combinations_and_remaining(l, n):
for c in combinations(l, n):
diff = [i for i in l if i not in c]
yield c, diff
for i in combinations_and_remaining([1, 2, 3, 4, 5], 2):
print(i)
Will output
((1, 2), [3, 4, 5])
((1, 3), [2, 4, 5])
((1, 4), [2, 3, 5])
((1, 5), [2, 3, 4])
((2, 3), [1, 4, 5])
((2, 4), [1, 3, 5])
((2, 5), [1, 3, 4])
((3, 4), [1, 2, 5])
((3, 5), [1, 2, 4])
((4, 5), [1, 2, 3])
(The combinations returns tuples; remaining elements are returned as lists for efficiency)
One slightly extravagant but fun way would be to use combinations twice:
from itertools import combinations
n = 5
k = 2
lst = list(range(1, n+1))
rslt = zip(combinations(lst, k), map(tuple, reversed(list(combinations(lst, n-k)))))
print(list(rslt))
# -> [((1, 2), (3, 4, 5)), ((1, 3), (2, 4, 5)), ((1, 4), (2, 3, 5)),
# ((1, 5), (2, 3, 4)), ((2, 3), (1, 4, 5)), ((2, 4), (1, 3, 5)),
# ((2, 5), (1, 3, 4)), ((3, 4), (1, 2, 5)), ((3, 5), (1, 2, 4)),
# ((4, 5), (1, 2, 3))]
You can avoid loops and improve readability by using sets, as such:
from itertools import combinations
input = [1,2,3,4,5]
for n in itertools.combinations(input, 2):
print(n , set(n) ^ set(input))
That is, of course, assuming there are no duplicates in the original, which will be lost in the conversion to a set.
I am trying to create a list containing sub-lists in python; like, the proper subset of a set. For example,
A = [1, 2, 3, 4]
Desired List = [[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4], [1, 2, 3], [1, 2, 4], [2, 3, 4]]
Thanks!
Since it seems you only want subsets of size 2 or more:
from itertools import combinations, chain
A = range(1, 5)
list(chain(*(combinations(A, r) for r in range(2, len(A)))))
# [(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4), (1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]
If you want all proper subsets, just change range(2, len(A)) to range(len(A)).
It looks like you want to get all the combinations from the list. Try using itertools.combinations
desired_list = itertools.combinations(A, 2)
I can do it by making use of the list indexes ...
lst =[1,2,3,4,5,6]
[ [lst[i] , lst[i+1]] for i in range( len(lst) - 1 )]
or:
lst =[1,2,3,4,5,6]
for i in range(len(lst)-1):
entities.append([lst[i],lst[i+1]])
But is there a smarter way? Maybe using iterators? What about performance?
For a general solution (since you asked for couples, triples, etc.), use itertools.tee:
from itertools import tee
def adjacent_tuples(iterable, n=2):
iterators = tee(iterable, n)
for i, iterator in enumerate(iterators):
for j in range(i):
next(iterator)
return zip(*iterators)
This uses a minimum of memory and works for any length of tuples:
>>> list(adjacent_tuples(range(8), 4))
[(0, 1, 2, 3), (1, 2, 3, 4), (2, 3, 4, 5), (3, 4, 5, 6), (4, 5, 6, 7)]
You received some clever answers here, but I'd like to suggest that the most obvious way to do this just uses built-in slice indexing. Like so:
def gen_k_slices(seq, k):
for i in range(len(seq) - k + 1):
yield seq[i:i+k]
Here's a little test driver:
TEST = [1, 2, 3, 4, 5, 6]
for k in range(8):
print("k={} -> {}".format(k, list(gen_k_slices(TEST, k))))
and its output:
k=0 -> [[], [], [], [], [], [], []]
k=1 -> [[1], [2], [3], [4], [5], [6]]
k=2 -> [[1, 2], [2, 3], [3, 4], [4, 5], [5, 6]]
k=3 -> [[1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6]]
k=4 -> [[1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 6]]
k=5 -> [[1, 2, 3, 4, 5], [2, 3, 4, 5, 6]]
k=6 -> [[1, 2, 3, 4, 5, 6]]
k=7 -> []
I don't like the result for k=0 either ;-)
You can use zip():
>>> lst = [1,2,3,4,5,6]
>>> list(zip(lst[:-1],lst[1:]))
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]
>>> list(zip(lst[:-2],lst[1:-1],lst[2:]))
[(1, 2, 3), (2, 3, 4), (3, 4, 5), (4, 5, 6)]
An iterator would be like this.
def iterate_couples(lst):
for i in range(len(lst) - 1):
yield [lst[i], lst[i + 1]]
You can zip iterators, one regular and another one shifted:
>>> it = iter(lst)
>>> it.next()
1
>>> zip(iter(lst), it)
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]
Here's an appropriate generator (using izip):
from itertools import izip
def my_zip(l):
i1 = iter(l)
i2 = iter(l)
i2.next()
for value in izip(i1, i2):
yield value
lst = [1,2,3,4,5,6]
print list(my_zip(lst)) # prints [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]