Using itertools.product repeat multiple times - python

I am trying to generate a list of unique lists each 5 elements long, the order is not important but there can't be any repeated elements. The first 3 elements needs to be from [1,2,3,4] and elements 4 and 5 from [5,6,7,8]. for example [1,2,3,7,8] is valid but [1,2,2,7,8] is not nor is [1,2,7,8,9]
The below code works but I am wondering is there a better way of incorporating the product function? something like d = product([L1, repeat=3][L4,repeat=2). From reading the docs the repeat keyword can only be used once, like this: d = product(L1,L4,repeat=2).
Any ideas how i could do this?
Thanks
from itertools import product
L1 = [1,2,3,4]
L2 = [1,2,3,4]
L3 = [1,2,3,4]
L4 = [5,6,7,8]
L5 = [5,6,7,8]
d = product(L1,L2,L3,L4,L5)
result=[]
for x in d:
if x.count(1)<2 and x.count(2)<2 and x.count(3)<2 and x.count(4)<2 and x.count(5)<2 and x.count(6)<2 and x.count(7)<2 and x.count(8)<2:
result.append(sorted(x))
result2 = []
for x in result:
if x not in result2:
result2.append(x)
print(result2)
result2
[[1, 2, 3, 5, 6],
[1, 2, 3, 5, 7],
[1, 2, 3, 5, 8],
[1, 2, 3, 6, 7],
[1, 2, 3, 6, 8],
[1, 2, 3, 7, 8],
[1, 2, 4, 5, 6],
[1, 2, 4, 5, 7],
[1, 2, 4, 5, 8],
[1, 2, 4, 6, 7],
[1, 2, 4, 6, 8],
[1, 2, 4, 7, 8],
[1, 3, 4, 5, 6],
[1, 3, 4, 5, 7],
[1, 3, 4, 5, 8],
[1, 3, 4, 6, 7],
[1, 3, 4, 6, 8],
[1, 3, 4, 7, 8],
[2, 3, 4, 5, 6],
[2, 3, 4, 5, 7],
[2, 3, 4, 5, 8],
[2, 3, 4, 6, 7],
[2, 3, 4, 6, 8],
[2, 3, 4, 7, 8]]

I would instead use itertools.combinations in combination with itertools.product:
from itertools import chain, combinations, product
result = list(
map(
list,
map(
chain.from_iterable,
product(
combinations([1, 2, 3, 4], 3),
combinations([5, 6, 7, 8], 2),
),
),
),
)

the repeat is going to repeat the result two times, in case anyone is wondering about it .
the product takes 1 parameter, the second is optional
for more details :
https://blog.teclado.com/python-itertools-part-1-product/

Related

Replacing items in a list in all possible permutations

Let's say I have a list or an array of the type:
mylist = [1, 2, 3, 4]
And I want to replace an item in this list. Normally I would use something like the following:
mylist[2] = 7
That works well. However, can someone explain how to create all possible permutations of mylist when replacing one or more items in mylist. For example, I want to create the following:
[7, 2, 3, 4]
[7, 7, 3, 4]
[7, 2, 7, 4]
[7, 7, 7, 4]
[7, 2, 3, 7]
...(and so on)
I know I can use itertools to generate all possible permutations, but how can I specify that I want to substitute an item in all possible locations in the list before generating the permutations? Here is how I tried to use itertools:
list(itertools.permutations([1,2,3,4,7], 4))
This doesn't work because it doesn't substitute 7 more than one time per permutation, and it also generates permutations that do not include the number 7.
Use itertools.combinations to find the indices to replace:
replace = 7
mylist = [1, 2, 3, 4]
for i in range(1, len(mylist) + 1):
for selected in itertools.combinations(range(len(mylist)), i):
res = mylist[:]
for n in selected:
res[n] = replace
print(res)
Output:
[7, 2, 3, 4]
[1, 7, 3, 4]
[1, 2, 7, 4]
[1, 2, 3, 7]
[7, 7, 3, 4]
[7, 2, 7, 4]
[7, 2, 3, 7]
[1, 7, 7, 4]
[1, 7, 3, 7]
[1, 2, 7, 7]
[7, 7, 7, 4]
[7, 7, 3, 7]
[7, 2, 7, 7]
[1, 7, 7, 7]
[7, 7, 7, 7]
You can create a function and just pass the list and value to that function and you get what you want :
import itertools
def replaced_it(list_1,value):
final_list = []
len_=len(list_1)
track_index = [k for k, j in enumerate(list_1)]
for i in range(len(track_index) + 1):
empty_list = [value]
replaced_one = list_1[:]
for ia in itertools.permutations(track_index, r=i):
if ia:
for i, j in zip(ia, empty_list * len(ia)):
replaced_one[i] = j
if replaced_one not in final_list:
final_list.append(replaced_one)
replaced_one = list_1[:]
return final_list
print(replaced_it([1,2,3,4],7))
output:
[[7, 2, 3, 4], [1, 7, 3, 4], [1, 2, 7, 4], [1, 2, 3, 7], [7, 7, 3, 4], [7, 2, 7, 4], [7, 2, 3, 7], [1, 7, 7, 4], [1, 7, 3, 7], [1, 2, 7, 7], [7, 7, 7, 4], [7, 7, 3, 7], [7, 2, 7, 7], [1, 7, 7, 7], [7, 7, 7, 7]]

Create a list of list with flexible input (Python) [duplicate]

This question already has answers here:
How can I make a for-loop pyramid more concise in Python? [duplicate]
(4 answers)
Closed 5 years ago.
I currently have a function that creates a list of lists like below using 3 nested for-loops.
[[1,1,1] , [1,1,2] , .... , [3,3,3]]
However, the problem is I can't use this function if someone wants the list of list to be something like
[[1,1,1,1,1,1,1] , ..... , [9,9,9,9,9,9,9]]
which has more numbers (from 1 - 9) and more elements (7 of 1's instead of 4).
Here's my current code:
def listofList():
temp = []
for i in range(1,4):
for j in range(1,4):
for k in range(1,4):
temp.append([i,j,k])
return temp
Can someone provide me with a better solution? I want my function listofList() to be flexible where it could receive an input for both the size of the list of list and the elements inside the list.
Try the following:
def listofList(subLen, totalLen):
final = [[item for i in range(subLen)] for item in range(1, totalLen+1)]
return final
>>> listofList(9, 9)
[[1, 1, 1, 1, 1, 1, 1, 1, 1], [2, 2, 2, 2, 2, 2, 2, 2, 2], [3, 3, 3, 3, 3, 3, 3, 3, 3], [4, 4, 4, 4, 4, 4, 4, 4, 4], [5, 5, 5, 5, 5, 5, 5, 5, 5], [6, 6, 6, 6, 6, 6, 6, 6, 6], [7, 7, 7, 7, 7, 7, 7, 7, 7], [8, 8, 8, 8, 8, 8, 8, 8, 8], [9, 9, 9, 9, 9, 9, 9, 9, 9]]
>>> listofList(9, 2)
[[1, 1, 1, 1, 1, 1, 1, 1, 1], [2, 2, 2, 2, 2, 2, 2, 2, 2]]
>>> listofList(2, 9)
[[1, 1], [2, 2], [3, 3], [4, 4], [5, 5], [6, 6], [7, 7], [8, 8], [9, 9]]
>>>

fill a one dimension space with predefined values [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I would like to fill a length with predefined "subLengths".
let say my subLength are : 3,4,5,6,7,10.
To fill a length of 15 I can use "10+5" , "3+4+3+5" ,"7+4+4" ,"7+5+3" ....
How could I get as an array one of theses results ?
Better : how could I get an array for several good results ? My maximum length is 70 and I guess It could be time consuming to get all the good results for this value.
I am a 3d artist, my coding skill is quiet limited and I just don't know how to deal with this problem .I can use Python or a language looking like C for that.
this code seems to work in my software :
def fillBuild(length, subLengths):
for i in range(len(subLengths)):
if subLengths[i] == length:
yield subLengths[i:i + 1]
elif subLengths[i] < length:
for subResult in fillBuild(length - subLengths[i] ,subLengths[i:] ):
yield subLengths[i:i + 1] + subResult
Recursive generator function (Python) producing all possible sublist permutations (with repetitions) of pool adding up to total:
from pprint import pprint
def sub_lists(pool, total):
for i in range(len(pool)):
if pool[i] == total:
yield pool[i:i + 1]
elif pool[i] < total:
for sub_list in sub_lists(pool, total - pool[i]):
yield pool[i:i + 1] + sub_list
pprint(list(sub_lists([3, 4, 5, 6, 7, 10], 15)))
[[3, 3, 3, 3, 3],
[3, 3, 3, 6],
[3, 3, 4, 5],
[3, 3, 5, 4],
[3, 3, 6, 3],
[3, 4, 3, 5],
[3, 4, 4, 4],
[3, 4, 5, 3],
[3, 5, 3, 4],
[3, 5, 4, 3],
[3, 5, 7],
[3, 6, 3, 3],
[3, 6, 6],
[3, 7, 5],
[4, 3, 3, 5],
[4, 3, 4, 4],
[4, 3, 5, 3],
[4, 4, 3, 4],
[4, 4, 4, 3],
[4, 4, 7],
[4, 5, 3, 3],
[4, 5, 6],
[4, 6, 5],
[4, 7, 4],
[5, 3, 3, 4],
[5, 3, 4, 3],
[5, 3, 7],
[5, 4, 3, 3],
[5, 4, 6],
[5, 5, 5],
[5, 6, 4],
[5, 7, 3],
[5, 10],
[6, 3, 3, 3],
[6, 3, 6],
[6, 4, 5],
[6, 5, 4],
[6, 6, 3],
[7, 3, 5],
[7, 4, 4],
[7, 5, 3],
[10, 5]]
Here's a recursive solution, using Python 2.7:
def fill(length, sublengths):
# IMPORTANT: this function will produce INCORRECT RESULTS if sublengths
# is not a list of unique integers sorted increasingly.
fillings = []
for i, sublength in enumerate(sublengths):
if sublength > length:
# if sublength is greater than length, there are no more allowable
# fillings (because sublengths are unique and are sorted
# increasingly), so we return the fillings collected so far;
return fillings
elif sublength == length:
# if sublength is exactly equal to length, then only one filling is
# possible, namely [sublength]; we append this filling to the
# fillings;
fillings.append([sublength])
else:
# we generate all the fillings that begin with sublength by
# prepending sublength to all the allowable fillings of
# (length - sublength), which we obtain by making a recursive call.
fillings.extend([[sublength] + subresult
for subresult in
fill(length - sublength, sublengths[i:])])
Example:
In [2]: fill(15, [3, 4, 5, 6, 7, 10])
Out[2]:
[[3, 3, 3, 3, 3],
[3, 3, 3, 6],
[3, 3, 4, 5],
[3, 4, 4, 4],
[3, 5, 7],
[3, 6, 6],
[4, 4, 7],
[4, 5, 6],
[5, 5, 5],
[5, 10]]
BTW: fill(70, [3, 4, 5, 6, 7, 10])) produces 1657 possible fillings, so you may want some additional criterion to whittle down the alternatives.
Some notes:
in order to avoid repeating solutions, we will require that each filling be ordered increasingly;
the key idea is this: suppose that the length to fill is L, and a1 < a2 < ... < an are the available sublengths. To find all the possible fillings of L that begin with a1 is tantamount to prepending a1 to all the fillings of L - a1. This is the rationale for the recursive call in the else block of fill. (When a function calls itself, as fill does, the function is said to be recursive.)
Since fill requires sublengths to be free of duplicates and sorted increasingly, we can use the following front-end function to ensure these conditions are satisfied:
def do_fill(length, sublengths):
return fill(length, sorted(set(sublengths)))
(NB: Below is a fairly detailed explanation of what the code does. If you already understand the code, you can safely skip the rest of this post.)
To better see what's going on, go back to the example above, and start by grouping the solutions according to the first sublength; you'll get the three groups shown below:
# group I
[3, 3, 3, 3, 3]
[3, 3, 3, 6]
[3, 3, 4, 5]
[3, 4, 4, 4]
[3, 5, 7]
[3, 6, 6]
# group II
[4, 4, 7]
[4, 5, 6]
# group III
[5, 5, 5]
[5, 10]
Now, compare the fillings in group I, all of which begin with 3, with the fillings for 15-3 = 12, using the sublengths [3, 4, 5, 6, 7, 10]:
In [3]: fill(15 - 3, [3, 4, 5, 6, 7, 10])
Out[3]:
[[3, 3, 3, 3],
[3, 3, 6],
[3, 4, 5],
[4, 4, 4],
[5, 7],
[6, 6]]
If now you prepend 3 to all these fillings, you'll get exactly the fillings in group I.
Now consider the fillings in group II, all of which begin with 4. Compare them with the fillings for 15 - 4 = 11, using the sublengths [4, 5, 6, 7, 10]:
In [4]: fill(15 - 4, [4, 5, 6, 7, 10])
Out[4]:
[4, 7],
[5, 6]
Again, if you prepend 4 to all these fillings you get exactly the fillings in group II.
You may wonder, why did I use [4, 5, 6, 7, 10] as the sublengths in the last call to fill above, and not [3, 4, 5, 6, 7, 10]? This is because I am interested only in fillings that are increasingly ordered and that begin with 4. This rules out any fillings that include 3.
Finally, to get the fillings in group III, prepend 5 to all the fillings for 15 - 5 = 10, using sublengths [5, 6, 7, 10]:
In [5]: fill(15 - 5, [5, 6, 7, 10])
Out[5]:
[[5, 5],
[10]]
If you are so inclined you can repeat the same sort of analysis for each of the subgroups. For example, you can group the fillings generated by fill(15 - 3, [3, 4, 5, 6, 7, 10]) according to their first element; you'd get 4 groups:
[3, 3, 3, 3]
[3, 3, 6]
[3, 4, 5]
[4, 4, 4]
[5, 7]
[6, 6]
These groups are obtained by prepending 3, 4, 5, or 6, respectively, to the fillings produced by
fill((15 - 3) - 3, [3, 4, 5, 6, 7, 10])
fill((15 - 3) - 4, [ 4, 5, 6, 7, 10])
fill((15 - 3) - 5, [ 5, 6, 7, 10])
fill((15 - 3) - 6, [ 6, 7, 10])
The analysis above just does "by hand" exactly what the fill function does.
One important thing to note is that, with every recursive call, the problem becomes simpler.
For example, in the process of generating filling [3, 5, 7] the following calls to fill got executed:
fill(15, [3, 4, 5, 6, 7, 10]) = fill(15, [3, 4, 5, 6, 7, 10])
fill(15 - 3, [3, 4, 5, 6, 7, 10]) = fill(12, [3, 4, 5, 6, 7, 10])
fill(15 - 3 - 5, [ 5, 6, 7, 10]) = fill( 7, [ 5, 6, 7, 10])
Note in particular the last one, fill(7, [5, 6, 7, 10]). One can spot its solution by inspection: only one filling of 7 is possible from sublengths [5, 6, 7, 10]. The recursion always ends with the solutions of these trivial cases. The ultimate solutions get assembled from these trivial ones.

filtering a list of entries in python

I need to filter a list of character ie
In [16]: list
Out[16]: [[1, 2, 3, 4, 5, 6, 7, 8], [2, 3, 6, 3, 6, 2, 7], [4, 5, 9, 3, 1, 8]]
characters to grep is, g = [4,8]
In [27]: a = filter(lambda x:g in x, list)
In [28]: a
Out[28]: []
But I am ending up with this. Can someone help me?
I need the output as
[[1, 2, 3, 4, 5, 6, 7, 8], [4, 5, 9, 3, 1, 8]]
Your issue is that g in x is never True because g is a list that and that is never within one of your sub-lists, e.g. ([4,8] in [4,8,7] returns False). The right approach with filter:
l = [[1, 2, 3, 4, 5, 6, 7, 8], [2, 3, 6, 3, 6, 2, 7], [4, 5, 9, 3, 1, 8]]
g = [4,8]
filter(lambda x:all(c in x for c in g), l)
# [[1, 2, 3, 4, 5, 6, 7, 8], [4, 5, 9, 3, 1, 8]]
Or list comprehension:
[item for item in l if all(c in item for c in g)]
# [[1, 2, 3, 4, 5, 6, 7, 8], [4, 5, 9, 3, 1, 8]]
Note, don't name your variables list, this shadows the built-in name

Better way to get sublist in python

I am working on the following problem:
This function returns a list of all possible sublists in L of length n without skipping elements in L. The sublists in the returned list should be ordered in the way they appear in L, with those sublists starting from a smaller index being at the front of the list.
Example 1, if L = [10, 4, 6, 8, 3, 4, 5, 7, 7, 2] and n = 4 then your function should return the list [[10, 4, 6, 8], [4, 6, 8, 3], [6, 8, 3, 4], [8, 3, 4, 5], [3, 4, 5, 7], [4, 5, 7, 7], [5, 7, 7, 2]]
My solution works but how can I make it shorter? What is a better way to do this?
def getSublists(L, n):
newN = n
myList = []
for i in range(len(L)):
orginalLen = L[i:n]
if(len(orginalLen) == n):
myList.append(L[i:n])
n = n + 1
else:
myList.append(L[i:n])
n = n + 1
if(newN == 1):
print(myList)
else:
print(myList[:len(myList)-(n-1)])
getSublists([10, 4, 6, 8, 3, 4, 5, 7, 7, 2],4)
getSublists([1], 1)
getSublists([0, 0, 0, 0, 0], 2)
OUTPUT
[[10, 4, 6, 8], [4, 6, 8, 3], [6, 8, 3, 4], [8, 3, 4, 5], [3, 4, 5, 7], [4, 5, 7, 7], [5, 7, 7, 2]]
[[1]]
[[0, 0], [0, 0], [0, 0], [0, 0]]
l = [1,2,3,4,5,6,87,9]
n = ..
print [l[i:i+n] for i in range(len(l)-n+1)]
maybe you need.
In one line:
get_sublists = lambda ls, n: [ls[x:x+n] for x in range(len(ls)-n+1)]
get_sublists([10, 4, 6, 8, 3, 4, 5, 7, 7, 2], 4)
[[10, 4, 6, 8], [4, 6, 8, 3], [6, 8, 3, 4], [8, 3, 4, 5], [3, 4, 5, 7], [4, 5, 7, 7], [5, 7, 7, 2]]
def get_sublists(L, n):
return [ L[i:i+n] for i in range(len(L)-n) ]
I completed the program a little better understanding of the reader.
def getSublists(L, n):
new_list = []
for i in range(len(L)-n+1):
a = L[i:i+n]
new_list.append(a)
return new_list
answer:
[[10, 4, 6, 8],
[4, 6, 8, 3],
[6, 8, 3, 4],
[8, 3, 4, 5],
[3, 4, 5, 7],
[4, 5, 7, 7],
[5, 7, 7, 2]]
This is pretty readable I think, to understand the concept. The idea here is to iterate through the numbers from 0 to the length of L, minus 4. And just take the sublist of L from your current index i, to i+4. Iterating to length-4 ensures you don't try to access an index out of bounds!
>>> for i in range(len(L)-4+1):
print L[i:i+4]
[10, 4, 6, 8]
[4, 6, 8, 3]
[6, 8, 3, 4]
[8, 3, 4, 5]
[3, 4, 5, 7]
[4, 5, 7, 7]
[5, 7, 7, 2]

Categories

Resources