is there a way to automatically generate a list of permutations with three value when you only give it two ?
E = {'M', 'F'}
permute_k = list(itertools.permutations(E, 3))
like the code above will give me a empty list like this []
but I want a list that contain the two value as three element like this [’MMM’, ’MMF’, ’MFM’, ...]
any suggestion
In this case you want a cartesian product, with a repeat arg
>>> list(itertools.product(E, repeat=3))
[('F', 'F', 'F'), ('F', 'F', 'M'), ('F', 'M', 'F'), ('F', 'M', 'M'), ('M', 'F', 'F'), ('M', 'F', 'M'), ('M', 'M', 'F'), ('M', 'M', 'M')]
and if you want the elements as strings instead of tuples you can str.join
>>> [''.join(i) for i in itertools.product(E, repeat=3)]
['FFF', 'FFM', 'FMF', 'FMM', 'MFF', 'MFM', 'MMF', 'MMM']
It is because itertools.permutations returns the subsequences of the input iterable. If you specify r > len(iterable) you will have an empty list. Your iterable should be 'MMMFFF' here. By the way a set is not an iterable so you have to manipulate list or a string instead.
E = 'MMMFFF' # or ['M', 'M', 'M', 'F', 'F', 'F']
permute_k = list(itertools.permutations(E, 3))
permute_k = [''.join(perm) for perm in permute_k] # to have a list of strings
Related
I have list of posiple letter for each letter in a word..and I want to find all possiple words.
for example the input is [[l,b],[e,d],[s,t]] this represent a word of 3 letter wher first letter could be l or b, second letter could be e or d and third letter is s or t. I wont the out put to be the product of these lists [les,let,bet,...and so on]. the list could be any length not only three.
I tried
res = list(map(prod, zip(test_list)))
but I get
[<itertools.product object at 0x0000024F65AEC600>, <itertools.product object at 0x0000024F65AEC640>, <itertools.product object at 0x0000024F65AEC680>, <itertools.product object at 0x0000024F65AEC6C0>]
I tried
word1=list(product(letter[0],letter[1],letter[2]))
it works perfectly but I want the code to accept any length pf list
You don't want to zip the test_list, just pass each element of it as an argument to product using the * operator:
>>> test_list = [['l','b'],['e','d'],['s','t']]
>>> import itertools
>>> list(itertools.product(*test_list))
[('l', 'e', 's'), ('l', 'e', 't'), ('l', 'd', 's'), ('l', 'd', 't'), ('b', 'e', 's'), ('b', 'e', 't'), ('b', 'd', 's'), ('b', 'd', 't')]
If you want the result to be in string form, use join:
>>> [''.join(p) for p in itertools.product(*test_list)]
['les', 'let', 'lds', 'ldt', 'bes', 'bet', 'bds', 'bdt']
Create combinations of item attributes in order.
Hello, I am trying to create all the combinations of a product in a particular order. The actual problem is quite large, so I have simplified it here but with the same concept. First time using itertools.
Say I am selling a t-shirt. It comes in 3 sizes (s,m,l), 3 colours (w,b,g) and 2 fits (slim,baggy). Put together these make the product code, but have to be in the order of size-colour-fit.
So the combinations are:
S-W-SLIM
S-W-BAGGY
S-B-SLIM
S-B-BAGGY
etc.
My program would need to output all the codes, which should be 3x3x2 = 18 combinations.
import itertools
size = ['S','M','L']
colour = ['W','B','G']
fit = ['slim','baggy']
options = itertools.product(size, colour,fit,[3])
print (options)
<itertools.product object at 0x03718E68>
[Finished in 0.1s]
I have had a look at combinations() and permutations() but they only take 2 input arguments?
Unsure where to go from here, TIA.
Convert it to a list:
print(list(options))
Then it will output:
[('S', 'W', 'slim'), ('S', 'W', 'baggy'), ('S', 'B', 'slim'), ('S', 'B', 'baggy'), ('S', 'G', 'slim'), ('S', 'G', 'baggy'), ('M', 'W', 'slim'), ('M', 'W', 'baggy'), ('M', 'B', 'slim'), ('M', 'B', 'baggy'), ('M', 'G', 'slim'), ('M', 'G', 'baggy'), ('L', 'W', 'slim'), ('L', 'W', 'baggy'), ('L', 'B', 'slim'), ('L', 'B', 'baggy'), ('L', 'G', 'slim'), ('L', 'G', 'baggy')]
Also, you can skip the last argument of [3]:
options = itertools.product(size, colour, fit)
It will output the same, you can check the length and it would be 18.
If you need dashed between them:
options = ['-'.join(i) for i in itertools.product(size, colour, fit)]
And the output of:
print(options)
Would be:
['S-W-slim', 'S-W-baggy', 'S-B-slim', 'S-B-baggy', 'S-G-slim', 'S-G-baggy', 'M-W-slim', 'M-W-baggy', 'M-B-slim', 'M-B-baggy', 'M-G-slim', 'M-G-baggy', 'L-W-slim', 'L-W-baggy', 'L-B-slim', 'L-B-baggy', 'L-G-slim', 'L-G-baggy']
First, I have noticed that there are many questions posted on sorting lists of tuples, however after looking over a few posts I did not see any of the questions with this particular format for the list. Apologies in advance then for a potential repeat question, however I think this should be simple.
Let the list of tuples be this:
my_list = [(('G', 'J', 'I'), 1.0), (('E', 'H', 'F'), 1.0), (('F', 'H', 'G'), 0.8889), (('I', 'K', 'J'), 0.8889), (('H', 'I', 'G'), 0.8889), (('H', 'J', 'I'), 0.875)]
Note that each tuple in the list consists of 1: another tuple of length 3 with 3 letters, and 2: a floating point number. My sorting objective is simple then: 1st sort the list of tuples by the floating point number, 2nd break any ties in the floating point number by then sorting by the first letter in the length-3 tuple, 3rd break any ties in that letter by sorting by the 2nd letter in the length-3 tuple. Desired output would then be:
sorted_list = [(('E', 'H', 'F'), 1.0), (('G', 'J', 'I'), 1.0), (('F', 'H', 'G'), 0.8889), (('H', 'I', 'G'), 0.8889), (('I', 'K', 'J'), 0.8889), (('H', 'J', 'I'), 0.875)]
in this particular example, sorting on the 2nd letter to break ties on the first letter did not appear, although it does in my larger dataset.
Thanks!
Here's one way to do it: the first sort is done in reverse on the float, while the ties are broken by sorting on the inner tuple:
srt_lst = sorted(my_list, key=lambda (x, y): (-y, x)) #python 2
print(srt_lst)
# [(('E', 'H', 'F'), 1.0), (('G', 'J', 'I'), 1.0), (('F', 'H', 'G'), 0.8889), (('H', 'I', 'G'), 0.8889), (('I', 'K', 'J'), 0.8889), (('H', 'J', 'I'), 0.875)]
In Python 3, you'll have to index the lambda's single parameter to access the items and use them for sorting:
srt_lst = sorted(my_list, key=lambda tup: (-tup[1], tup[0]))
I have been working on this looping problem for a bit now. How do I loop through a list containing a single string and tuple, while appending the tuple to the preceding string? For example:
gen = ['A', ('x', 'y'), ('t', 'u'), 'B', ('y', 't'), 'B', ('a', 'z')]
fam = ['A', 'B']
Fortunately fam also contains the single strings imbeded within gen. In the end I would like the following.
result = [('A',('x','y')), ('A', ('t', 'u')), ('B', ('y', 't')), ('B', ('a', 'z'))
Notice that the tuples following a single string (e.g. 'A') are appending to it.
How do I loop through gen so that the tuples are appending with single strings preceeding it? So far, I have something like the following. Which appends all the combinations in the gen, and then some. I foolishly created a duplicate gen, i.e. gen2 to help with looping, to no avail.
gen = ['A', ('x', 'y'), ('t', 'u'), 'B', ('y', 't'), 'B', ('a', 'z')]
fam = ['A', 'B']
gen2 = ['A', ('x', 'y'), ('t', 'u'), 'B', ('y', 't'), 'B', ('a', 'z')]
result = []
for f in fam:
for g in gen:
if len(g) == 2:
for g2 in gen2:
if g2 == f:
result.append((g2,f))
print result
I apologize if my ramble is too confusing. I appreciate any insight.
You can do it in a single loop and without using fam if you keep track of the last string you came across. It only works properly if the first element of gen is a string, though.
gen = ['A', ('x', 'y'), ('t', 'u'), 'B', ('y', 't'), 'B', ('a', 'z')]
result = []
lastStringSeen = None
for i in gen:
if isinstance(i, str):
lastStringSeen = i
else: #must be a tuple
result.append((lastStringSeen, i))
print result
output:
[('A', ('x', 'y')), ('A', ('t', 'u')), ('B', ('y', 't')), ('B', ('a', 'z'))]
I'm using Python 2.7.
Let's say I have a list like so:
string_list = ['hello', 'apple', 'green', 'paint', 'sting']
Where each string in the list is the same length.
I want to create a generator that would be doing something like the following code:
for i in xrange(len(string_list)):
my_gen = (ch for a_string[i] in string_list)
So the first run, my_gen would have 'h', 'a', 'g', 'p', s'. The next run it would have 'e', 'p', 'r', 'a', 't'.
Just use the built-in function zip -
like in
for letters in zip('hello', 'apple', 'green', 'paint', 'sting'):
print letters
zip is a built-in that does just that: combine one element of each iterable in a tuple, for each iteration.
Running the above example, you have:
>>> for letters in zip('hello', 'apple', 'green', 'paint', 'sting'):
... print letters
...
('h', 'a', 'g', 'p', 's')
('e', 'p', 'r', 'a', 't')
('l', 'p', 'e', 'i', 'i')
('l', 'l', 'e', 'n', 'n')
('o', 'e', 'n', 't', 'g')
izip does exactly what you want:
from itertools import izip
for letters in izip(*string_list):
print letters
The * operator unpacks your string_list so that izip sees it as five sequences of characters, instead of just a single list of strings.
Output:
('h', 'a', 'g', 'p', 's')
('e', 'p', 'r', 'a', 't')
('l', 'p', 'e', 'i', 'i')
('l', 'l', 'e', 'n', 'n')
('o', 'e', 'n', 't', 'g')
The built-in zip function works too, but it's not lazy (i.e. it immediately returns a list of all the tuples, instead of generating them one at a time).
The following recipe comes from the itertools documentation:
from itertools import islice, cycle
def roundrobin(*iterables):
"roundrobin('ABC', 'D', 'EF') --> A D E B F C"
# Recipe credited to George Sakkis
pending = len(iterables)
nexts = cycle(iter(it).next for it in iterables)
while pending:
try:
for next in nexts:
yield next()
except StopIteration:
pending -= 1
nexts = cycle(islice(nexts, pending))
Besides being very fast, one advantage of this approach is that it works well if the input iterables are of different lengths.
Use the zip function that takes several lists (iterables) and yields tuples of corresponding items:
zip(*string_list)
yields (successively)
[('h', 'a', 'g', 'p', 's'),
('e', 'p', 'r', 'a', 't'),
('l', 'p', 'e', 'i', 'i'),
('l', 'l', 'e', 'n', 'n'),
('o', 'e', 'n', 't', 'g')]
def foo(string_list):
for i in xrange(len(string_list)):
yield (a_string[i] for a_string in string_list)
string_list = ['hello', 'apple', 'green', 'paint', 'sting']
for nth_string_list in foo(string_list):
for ch in nth_string_list:
print ch
val = zip('hello','apple','green','paint','sting')
or zip(*string_list)
print val[0]
output = ('h', 'a', 'g', 'p', 's')
print val[1]
output = ('e', 'p', 'r', 'a', 't')