Related
I'd like to make nested list
given_list = [[0, 1, 2], [0, 1, 2], [0, 1, 2]] # each element : range(0, n), num of element : m
new_list = [[0, 0, 0], [0, 0, 1], [0, 0, 2], [0, 1, 0], ..., [2, 2, 2]] # total num : n^m
How do I make it?
I tried to overlap the for statement m times, but I don't think it's pythonic.
Looks like you are trying to compute the product of the lists in given_list:
> from itertools import product
> list(product(*given_list))
[(0, 0, 0), (0, 0, 1), (0, 0, 2), (0, 1, 0), (0, 1, 1), (0, 1, 2), (0, 2, 0), (0, 2, 1), (0, 2, 2), (1, 0, 0), (1, 0, 1), (1, 0, 2), (1, 1, 0), (1, 1, 1), (1, 1, 2), (1, 2, 0), (1, 2, 1), (1, 2, 2), (2, 0, 0), (2, 0, 1), (2, 0, 2), (2, 1, 0), (2, 1, 1), (2, 1, 2), (2, 2, 0), (2, 2, 1), (2, 2, 2)]
If you really need a list of lists, rather than a list of tuples, you'll have to call list on each element.
[list(t) for t in product(*given_list)]
Good morning!
I'm trying to generate a new list out of two lists, by using multiplication operation.
Below I show you step by step what I did:
import itertools
from itertools import product
import numpy as np
import pandas as pd
Parameter_list=[]
Parameter=[range(0,2,1),range(0,2,1)]
Parameter_list=list(itertools.product(*Parameter))
print(Parameter_list)
[(0, 0), (0, 1), (1, 0), (1, 1)]
Then I deleted the first value, which is basically the null matrix:
del Parameter_list[0]
print(Parameter_list)
[(0, 1), (1, 0), (1, 1)]
I proceeded by creating the two paramter list:
Parameter_A=[range(1,2,1),range(3,6,2),range(10,20,10)]
Parameter_A=list(itertools.product(*Parameter_A))
Parameter_B=[range(0,2,1),range(4,6,2),range(10,20,10)]
Parameter_B=list(itertools.product(*Parameter_B))
print(Parameter_A)
print(Parameter_B)
[(1, 3, 10), (1, 5, 10)]
[(0, 4, 10), (1, 4, 10)]
And combined the lists:
comb=list(product(Parameter_A,Parameter_B))
print(comb)
[((1, 3, 10), (0, 4, 10)),
((1, 3, 10), (1, 4, 10)),
((1, 5, 10), (0, 4, 10)),
((1, 5, 10), (1, 4, 10))]
Until here no prob. But now I'm struggling to create a new list from multiplying the Parameter List with the comb list. The desired output is the following:
[((0, 0, 0), (0, 4, 10)),
((0, 0, 0), (1, 4, 10)),
((0, 0, 0), (0, 4, 10)),
((0, 0, 0), (1, 4, 10)),
((1, 3, 10), (0, 0, 0)),
((1, 3, 10), (0, 0, 0)),
((1, 5, 10), (0, 0, 0)),
((1, 5, 10), (0, 0, 0)),
((1, 3, 10), (0, 4, 10)),
((1, 3, 10), (1, 4, 10)),
((1, 5, 10), (0, 4, 10)),
((1, 5, 10), (1, 4, 10))]
Can someone help me? Many thanks!
Doing this with lists instead of with a numpy array is not the most convenient choice. That said, it's still something you can do with a one-liner.
prod = [tuple(i if j != 0 else (0,) * len(i) for i, j in zip(comb_items, bool_items))
for comb_items, bool_items in itertools.product(comb, Parameter_list)]
>>> prod
[((0, 0, 0), (0, 4, 10)),
((1, 3, 10), (0, 0, 0)),
((1, 3, 10), (0, 4, 10)),
((0, 0, 0), (1, 4, 10)),
((1, 3, 10), (0, 0, 0)),
((1, 3, 10), (1, 4, 10)),
((0, 0, 0), (0, 4, 10)),
((1, 5, 10), (0, 0, 0)),
((1, 5, 10), (0, 4, 10)),
((0, 0, 0), (1, 4, 10)),
((1, 5, 10), (0, 0, 0)),
((1, 5, 10), (1, 4, 10))]
I am assuming that the order of the outputs isn't critical and that the Parameter_list will always be booleans. Both of these things can be pretty easily changed if needed.
This question already has answers here:
How to use list comprehension with .extend list method? [duplicate]
(2 answers)
How can I use a list comprehension to extend a list in python? [duplicate]
(6 answers)
Python: How to extend or append multiple elements in list comprehension format?
(2 answers)
Closed 4 years ago.
Is there a 1-liner equivalent (using list comprehension) for the following:
a = []
for i in range(6):
a.extend(((-i,i,0,2),(-i-1,i,0,6)))
a = tuple(a)
I was thinking something like
tuple(((-i,i,0,2),(-i-1,i,0,6)) for i in range(6))
but this gives:
(((0, 0, 0, 2), (-1, 0, 0, 6)),
((-1, 1, 0, 2), (-2, 1, 0, 6)),
((-2, 2, 0, 2), (-3, 2, 0, 6)),
((-3, 3, 0, 2), (-4, 3, 0, 6)),
((-4, 4, 0, 2), (-5, 4, 0, 6)),
((-5, 5, 0, 2), (-6, 5, 0, 6)))
which is not what I want.
Desired output
((0, 0, 0, 2),
(-1, 0, 0, 6),
(-1, 1, 0, 2),
(-2, 1, 0, 6),
(-2, 2, 0, 2),
(-3, 2, 0, 6),
(-3, 3, 0, 2),
(-4, 3, 0, 6),
(-4, 4, 0, 2),
(-5, 4, 0, 6),
(-5, 5, 0, 2),
(-6, 5, 0, 6))
You can use a nested list comprehension.
>>> [t for i in range(6) for t in ((-i,i,0,2), (-i-1,i,0,6))]
>>>
[(0, 0, 0, 2),
(-1, 0, 0, 6),
(-1, 1, 0, 2),
(-2, 1, 0, 6),
(-2, 2, 0, 2),
(-3, 2, 0, 6),
(-3, 3, 0, 2),
(-4, 3, 0, 6),
(-4, 4, 0, 2),
(-5, 4, 0, 6),
(-5, 5, 0, 2),
(-6, 5, 0, 6)]
It reads like this
[what I want (t) | for loops as if writing non-listcomp code]
and is thus equivalent to
result = []
for i in range(6):
for t in ((-i,i,0,2), (-i-1,i,0,6)):
result.append(t)
Python:
How to efficiency execute a multidimensional loop, when the number of indexes to loop is dynamic.
Assume an array var_size containing the size of each variable
var_size = [ 3, 4, 5 ]
and a function 'loop' which will call 'f(current_state)' for each point.
def f(state): print state
loop(var_size, f)
This call would call f in the following order:
f( [ 0, 0, 0])
f( [ 0, 0, 1])
f( [ 0, 0, 2])
f( [ 0, 1, 0])
etc....
You can do this with itertools.product:
>>> print list(itertools.product(*(range(x) for x in reversed([3,4,5]))))
[(0, 0, 0), (0, 0, 1), (0, 0, 2), (0, 1, 0), (0, 1, 1), (0, 1, 2), (0, 2, 0), (0, 2, 1), (0, 2, 2), (0, 3, 0), (0, 3, 1), (0, 3, 2), (1, 0, 0), (1, 0, 1), (1, 0, 2), (1, 1, 0), (1, 1, 1), (1, 1, 2), (1, 2, 0), (1, 2, 1), (1, 2, 2), (1, 3, 0), (1, 3, 1), (1, 3, 2), (2, 0, 0), (2, 0, 1), (2, 0, 2), (2, 1, 0), (2, 1, 1), (2, 1, 2), (2, 2, 0), (2, 2, 1), (2, 2, 2), (2, 3, 0), (2, 3, 1), (2, 3, 2), (3, 0, 0), (3, 0, 1), (3, 0, 2), (3, 1, 0), (3, 1, 1), (3, 1, 2), (3, 2, 0), (3, 2, 1), (3, 2, 2), (3, 3, 0), (3, 3, 1), (3, 3, 2), (4, 0, 0), (4, 0, 1), (4, 0, 2), (4, 1, 0), (4, 1, 1), (4, 1, 2), (4, 2, 0), (4, 2, 1), (4, 2, 2), (4, 3, 0), (4, 3, 1), (4, 3, 2)]
Note that I'm generating tuples instead of lists, but that's easy to fix if you really need to.
So, to me it looks like you want:
map(f,itertools.product(*map(range,reversed(var_size))))
Make a list initialized to 0s, as many entries as are in var_size. We treat this list as a list of 'tumblers' - we increment the last one in the list until it overflows its limit (aka var_size at the same point into the list). If so, we set it to 0, go one left and repeat the increment/overflow check until we either do not overflow (reset the 'which tumbler are we looking at' variable back to the last and continue) or overflow all entries of the list (we're done, we looped all the way around), then perform the next call.
I don't know if this is optimal or pythonic, but it is O(n).
This code does the job - And it has the advantage of not creating the list. However, it not that elegant....
Any ideas on how to get this better?
def loop(var_size, f):
nb = len(var_size)
state = [0]*nb
ok = True
while ok:
f(state)
for i in range(nb-1, -1, -1):
state[i] = state[i]+1
if state[i] < var_size[i]:
break
else:
if i == 0:
ok = False
break
else:
state[i] = 0
var_size = [3,4,5]
def f(state):
print state
loop(var_size, f)
n=int(raw_input('enter the number of mcnuggets you want to buy : ')) #total number of mcnuggets you want yo buy
for a in range(1,n) and b in range(1,n) and c in range(1,n) :
if (6*a+9*b+20*c==n):
print 'number of packs of 6 are ',a
print 'number of packs of 9 are ',b
print 'number of packs of 20 are',c
i am new to programming and i am learning python.the code above gives errors. Any suggestion.?.
You should use nested loops:
for a in range(1, n):
for b in range(1, n):
for c in range(1, n):
if ...
Or even better:
import itertools
for a, b, c in itertools.product(range(1, n + 1), repeat=3):
if ...
I think you should start the ranges from 0, otherwise you will only get answers that include at least one of each size. You can also make less work for the computer since you know that there will never be more than n/6 packs of 6 required etc. This can be a big saving - for 45 nuggets you only need to test 144 cases compared to 97336
from itertools import product
n=int(raw_input('enter the number of mcnuggets you want to buy : ')) #total number of mcnuggets you want to buy
for a,b,c in product(range(n//6+1), range(n//9+1), range(n//20+1)) :
if (6*a+9*b+20*c==n):
print 'number of packs of 6 are ',a
print 'number of packs of 9 are ',b
print 'number of packs of 20 are',c
itertools.product gives the cartesian product of the 3 ranges. For example
>>> from itertools import product
>>> list(product(range(3),range(4),range(5)))
[(0, 0, 0), (0, 0, 1), (0, 0, 2), (0, 0, 3), (0, 0, 4), (0, 1, 0), (0, 1, 1), (0, 1, 2), (0, 1, 3), (0, 1, 4), (0, 2, 0), (0, 2, 1), (0, 2, 2), (0, 2, 3), (0, 2, 4), (0, 3, 0), (0, 3, 1), (0, 3, 2), (0, 3, 3), (0, 3, 4), (1, 0, 0), (1, 0, 1), (1, 0, 2), (1, 0, 3), (1, 0, 4), (1, 1, 0), (1, 1, 1), (1, 1, 2), (1, 1, 3), (1, 1, 4), (1, 2, 0), (1, 2, 1), (1, 2, 2), (1, 2, 3), (1, 2, 4), (1, 3, 0), (1, 3, 1), (1, 3, 2), (1, 3, 3), (1, 3, 4), (2, 0, 0), (2, 0, 1), (2, 0, 2), (2, 0, 3), (2, 0, 4), (2, 1, 0), (2, 1, 1), (2, 1, 2), (2, 1, 3), (2, 1, 4), (2, 2, 0), (2, 2, 1), (2, 2, 2), (2, 2, 3), (2, 2, 4), (2, 3, 0), (2, 3, 1), (2, 3, 2), (2, 3, 3), (2, 3, 4)]
If you want to have values from multiple sequences in a for loop then you can use zip, for example:
for (a,b,c) in zip(xrange(1,n), xrange(1,n), xrange(1,n)) :
....
Of course it is a waste repeating the same range, but judging from the title of your post I guess that using the same range is only and example.