Let say that I have n lists and they are not disjoint. I want to make every combination of n elements which I get one from every lists I have but in that combination there are different elements and there are no double combination. So, [1,1,2] isn't allowed and [1,2,3] is same as [2,1,3].
For example, I have A=[1,2,3], B=[2,4,1], and C=[1,5,3]. So, the output that I want is [[1,2,5],[1,2,3],[1,4,5],[1,4,3],[2,4,1],[2,4,5],[2,4,3],[3,2,5],[3,4,5],[3,1,5]].
I have search google and I think function product in module itertools can do it. But, I have no idea how to make no same elements in every combinations and no double combinations.
Maybe something like:
from itertools import product
A=[1,2,3]
B=[2,4,1]
C=[1,5,3]
L = list(set([ tuple(sorted(l)) for l in product(A,B,C) if len(set(l))==3 ]))
Of course you would have to change 3 ot the relevant value if you work with more than 3 lists.
how about this? create a dicitonary with the sorted permutations as key. accept values only if all the three integers are different:
from itertools import product
A=[1,2,3]
B=[2,4,1]
C=[1,5,3]
LEN = 3
dct = {tuple(sorted(item)): item for item in product(A,B,C)
if len(set(item)) == LEN}
print(dct)
vals = list(dct.values())
print(vals)
Related
I would like to have all possible combinations of lists of a given size.
Lets say for example, I have a given list K, such as K = [3, 5, 2]. With the following code I get what I desire. But how do I generalize this for any list of a given size, without just adding for loops?
assignment= []
for l in range(K[0]):
for m in range(K[1]):
for n in range(K[2]):
a = [l,m,n]
assignment.append(a)
The itertools library can often help with things like this. itertools.product() in particular, using * to pass it a list or iterator of ranges:
list(itertools.product(*(range(n) for n in K))
or
list(itertools.product(*map(range, K)))
Consider this list of sets
my_input_list= [
{1,2,3,4,5},
{2,3,7,4,5},
set(),
{1,2,3,4,5,6},
set(),]
I want to get the only exclusive elements 6 and 7 as the response, list or set. Set preferred.
I tried
print reduce(set.symmetric_difference,my_input_list) but that gives
{2,3,4,5,6,7}
And i tried sorting the list by length, smallest first raises an error due to two empty sets. Largest first gives the same result as unsorted.
Any help or ideas please?
Thanks :)
Looks like the most straightforward solution is to count everything and return the elements that only appear once.
This solution uses chain.from_iterable (to flatten your sets) + Counter (to count things). Finally, use a set comprehension to filter elements with count == 1.
from itertools import chain
from collections import Counter
c = Counter(chain.from_iterable(my_input_list))
print({k for k in c if c[k] == 1})
{6, 7}
A quick note; the empty literal {} is used to indicate an empty dict, not set. For the latter, use set().
You could use itertools.chain and collection.Counter:
from itertools import chain
from collections import Counter
r = {k for k,v in Counter(chain.from_iterable(my_input_list)).items() if v==1}
I need to do this: I have list of integers, i make all possible combinations containing 3 of these numbers, and output is list containing sums of these combinations. (not sum of all combinations together, but for each combination one sum)
My algorithm do it in this way: make list of all possible combinations, then count sum of each combination and save it into list, what is too uneffective if number of integers is large. Here is little sample in python:
import itertools
array=[1,2,3,4]
combs=[]
els = [list(x) for x in itertools.combinations(array, 3)]
combs.extend(els)
result=list(map(sum, combs))
Could you please come up with some more effective solution? Maybe if there is some way of making it a loop where there isn't made a list of combinations at first and counted sum of each combination at second but rather it straight counts sum of just created combination, saves it into list and then continues to another one until all combinations and sums are done.
sum() works with any iterable, not just lists. You could make the code more efficient by applying it directly to the combinations' tuples:
result = [sum(c) for c in itertools.combinations(array, 3)]
If you want to process the result lazily, you can use a generator expression as well:
result = (sum(c) for c in itertools.combinations(array, 3))
I have some sets I would like to take the Cartesian product of, which is working well. However, I want to remove all elements of this new set which are identical under a permutation of the elements.
For example, take the following code:
import itertools as ittools
x = 2
y = 3
z = 5
flist = list(ittools.product([x,y,z],repeat=3))
for f in flist:
print reduce(lambda a,b: a*b, f)
This code find the Cartesian product of the set {2,3,5} and returns the product of all three components of each element in the resulting set. However, some numbers appear multiple times, i.e. 12 can be written as 2*2*3, 2*3*2, or 3*2*2. I would like to remove all but one instance of these duplicates.
I know that this fundamentally a combinatorics problem, but this seems like there is probably a nice solution in Python that doesn't involve doing an extra pass over the list like I did here to compute some identifier for each element of the Cartesian product.
You want combinations_with_replacement, not product:
itertools.combinations_with_replacement([x, y, z], 3)
Use a dict to map each unique product to the most recently seen tuple.
d = {reduce(operator.mul, f): f for f in flist}
If you would need to treat tuples that aren't permutations of each other as distinct elements, you'll need a more complicated key that incorporates a canonical representation of the tuple.
from operator import mul
d = {(tuple(sorted(f)), reduce(mul, f)): f for f in flist}
Actually, once you do that, you don't need to map the tuple/product pair to a tuple; you can just maintain a set of pairs:
d = {(tuple(sorted(f)), reduce(mul, f)) for f in flist}
In any case, retrieving just the tuples is as simple as
tuples = d.values() # In the first two cases
tuples = {x for x,y in d} # In the third case
I have used the following script to generate all combinations:
import itertools
x = 7
my_list = range(1, 11)
for k in [x]:
for sublist in itertools.combinations(my_list, k):
print sublist
For the second part I will take 6 random elements from range(1, 11). Let's call them my_second_list.
I need to generate the minimum number of combinations of my_list in order to obtain at least one combination to include let's say 5 elements from my_second_list.
Any ideas on how to do that?
import itertools
x = 7
my_list = range(1,11)
for k in [x]: # isn't this just 7?
your_output = (combination for combination in itertools.combinations(my_list,k) if all(element in combination for element in [1,2,3,4,5]))
It's ugly as heck, but that's how I'd do it (if I'm understanding your question correctly. You're trying to get only those combinations that contain a certain subset of items, right? If you want all combinations BEFORE and INCLUDING that first combination that contains the subset of items, I'd do:
accumulator = list()
subset = [1,2,3,4,5] # or whatever
for k in [x]:
for combination in itertools.combinations(my_list,k):
accumulator.append(combination)
if all(el in combination for el in subset):
break
Depending on your exact use case you may want to consider defining subset as a set (e.g. {1,2,3,4,5}) and do subset.issubset(set(combination)) but it's hard to tell if that's better or not without doing some profiling.