Using python I have to get all the permutations of given subset using python.
I used itertools.permutation but result is a bit different.
Think of a machine and it has a maximum capacity, and we have products can be produced together, and we have to fill the capacity of machine.
Output format is not important, I used a dictionary to describe it. I will make a calculation after getting this combinations.
For example :
products = {'x','y','z','a'}
machine_capcacity = 8
#required output as follows:
{'x':5,'y':1,'z':1,'a':1}
{'x':4,'y':2,'z':1,'a':1}
{'x':4,'y':1,'z':2,'a':1}
{'x':4,'y':1,'z':1,'a':2}
{'x':3,'y':3,'z':1,'a':1}
{'x':3,'y':1,'z':3,'a':1}
{'x':3,'y':1,'z':1,'a':3}
{'x':3,'y':2,'z':2,'a':1}
{'x':3,'y':2,'z':1,'a':2}
{'x':3,'y':1,'z':2,'a':2}
{'x':2,'y':4,'z':1,'a':1}
# ...
{'x':6,'y':1,'z':1} # This can't be in results,since need at least 1 element of product
{'x':4,'y':1,'z':1,'a':1} # This can't be in results,since we need to fill the capacity
And we dont want repeating elements:
{'x':5,'y':1,'z':1,'a':1}
and
{'a':1,'y':1,'z':1,'x':5}
is same thing for us.
Here is a solution not relying on itertools since it's getting contrived with all the constraints (a product yielding unique results and a minimum of 1 appearance per product):
products = {'x','y','z','a'}
machine_capacity=8
def genCap(capacity = machine_capacity,used = 0):
if used == len(products)-1: yield capacity,None
else:
for i in range(1,2+capacity-len(products)+used):
yield i,genCap(capacity-i,used+1)
def printCaps(caps,current = []):
if caps is None:
print(dict(zip(products,current)))
return
for i in caps:
printCaps(i[1],current+[i[0]])
printCaps(genCap())
might be optimize-able with tail recursion and the like. Looks almost like groupby, but I can't see an easy way to use that.
For posterity I leave my old solution - product repeats counts, so filtering it becomes a problem of it's own:
You confused product with permutation. Here is a quick solution using itertools product, and the Counter collection to create the output you want:
from collections import Counter
from itertools import product
products = {'x','y','z','a'}
machine_capacity=8
for x in filter(lambda x: len(x) == len(products),
map(Counter,product(products,repeat=machine_capacity))):
print(dict(x))
Note both product and map are lazy, so they won't be evaluated until you need them. Counter provides the output you want, and converting to dict cleans it up. Note no order is guaranteed anywhere. The filter is used to make sure all your products appear at least once (length of counter equals that of products) - and it is also lazy, so only evaluated when you need it.
You can use a recursive function to find all possible combinations of the values in range(machine_capacity) that both sum to 8 and are unique. Then, the elements in products can be mapped to each element in the sublists of the combinations found:
products = ['x','y','z','a']
machine_capacity = 8
def combinations(d, current = []):
if len(current) == len(products):
yield current
else:
for i in range(machine_capacity):
if sum(current+[i]) <= machine_capacity:
yield from combinations(d, current+[i])
data = [dict(zip(products, i)) for i in filter(lambda x:sum(x) == 8 and len(x) == len(set(x)), combinations(machine_capacity))]
Output:
[{'a': 5, 'x': 0, 'z': 2, 'y': 1}, {'a': 4, 'x': 0, 'z': 3, 'y': 1}, {'a': 3, 'x': 0, 'z': 4, 'y': 1}, {'a': 2, 'x': 0, 'z': 5, 'y': 1}, {'a': 5, 'x': 0, 'z': 1, 'y': 2}, {'a': 1, 'x': 0, 'z': 5, 'y': 2}, {'a': 4, 'x': 0, 'z': 1, 'y': 3}, {'a': 1, 'x': 0, 'z': 4, 'y': 3}, {'a': 3, 'x': 0, 'z': 1, 'y': 4}, {'a': 1, 'x': 0, 'z': 3, 'y': 4}, {'a': 2, 'x': 0, 'z': 1, 'y': 5}, {'a': 1, 'x': 0, 'z': 2, 'y': 5}, {'a': 5, 'x': 1, 'z': 2, 'y': 0}, {'a': 4, 'x': 1, 'z': 3, 'y': 0}, {'a': 3, 'x': 1, 'z': 4, 'y': 0}, {'a': 2, 'x': 1, 'z': 5, 'y': 0}, {'a': 5, 'x': 1, 'z': 0, 'y': 2}, {'a': 0, 'x': 1, 'z': 5, 'y': 2}, {'a': 4, 'x': 1, 'z': 0, 'y': 3}, {'a': 0, 'x': 1, 'z': 4, 'y': 3}, {'a': 3, 'x': 1, 'z': 0, 'y': 4}, {'a': 0, 'x': 1, 'z': 3, 'y': 4}, {'a': 2, 'x': 1, 'z': 0, 'y': 5}, {'a': 0, 'x': 1, 'z': 2, 'y': 5}, {'a': 5, 'x': 2, 'z': 1, 'y': 0}, {'a': 1, 'x': 2, 'z': 5, 'y': 0}, {'a': 5, 'x': 2, 'z': 0, 'y': 1}, {'a': 0, 'x': 2, 'z': 5, 'y': 1}, {'a': 1, 'x': 2, 'z': 0, 'y': 5}, {'a': 0, 'x': 2, 'z': 1, 'y': 5}, {'a': 4, 'x': 3, 'z': 1, 'y': 0}, {'a': 1, 'x': 3, 'z': 4, 'y': 0}, {'a': 4, 'x': 3, 'z': 0, 'y': 1}, {'a': 0, 'x': 3, 'z': 4, 'y': 1}, {'a': 1, 'x': 3, 'z': 0, 'y': 4}, {'a': 0, 'x': 3, 'z': 1, 'y': 4}, {'a': 3, 'x': 4, 'z': 1, 'y': 0}, {'a': 1, 'x': 4, 'z': 3, 'y': 0}, {'a': 3, 'x': 4, 'z': 0, 'y': 1}, {'a': 0, 'x': 4, 'z': 3, 'y': 1}, {'a': 1, 'x': 4, 'z': 0, 'y': 3}, {'a': 0, 'x': 4, 'z': 1, 'y': 3}, {'a': 2, 'x': 5, 'z': 1, 'y': 0}, {'a': 1, 'x': 5, 'z': 2, 'y': 0}, {'a': 2, 'x': 5, 'z': 0, 'y': 1}, {'a': 0, 'x': 5, 'z': 2, 'y': 1}, {'a': 1, 'x': 5, 'z': 0, 'y': 2}, {'a': 0, 'x': 5, 'z': 1, 'y': 2}]
Related
Depending on your few on my approach this is either a question about using np.unique() on awkward1 arrays or a call for a better approach:
Let a and b be two awkward1 arrays of the same outer length (number of events) but different inner lengths. For example:
a = [[1, 2], [3] , [] , [4, 5, 6]]
b = [[7] , [3, 5], [6], [8, 9]]
Let f: (x, y) -> z be a function that acts on two numbers x and y and results in the number z. For example:
f(x, y):= y - x
The idea is to compare every element in a with every element in b via f for each event and filter out the matches of a and b pairs that survive some cut applied to f. For example:
f(x, y) < 4
My approach for this is:
a = ak.from_iter(a)
b = ak.from_iter(b)
c = ak.cartesian({'x':a, 'y':b})
#c= [[{'x': 1, 'y': 7}, {'x': 2, 'y': 7}], [{'x': 3, 'y': 3}, {'x': 3, 'y': 5}], [], [{'x': 4, 'y': 8}, {'x': 4, 'y': 9}, {'x': 5, 'y': 8}, {'x': 5, 'y': 9}, {'x': 6, 'y': 8}, {'x': 6, 'y': 9}]]
i = ak.argcartesian({'x':a, 'y':b})
#i= [[{'x': 0, 'y': 0}, {'x': 1, 'y': 0}], [{'x': 0, 'y': 0}, {'x': 0, 'y': 1}], [], [{'x': 0, 'y': 0}, {'x': 0, 'y': 1}, {'x': 1, 'y': 0}, {'x': 1, 'y': 1}, {'x': 2, 'y': 0}, {'x': 2, 'y': 1}]]
diff = c['y'] - c['x']
#diff= [[6, 5], [0, 2], [], [4, 5, 3, 4, 2, 3]]
cut = diff < 4
#cut= [[False, False], [True, True], [], [False, False, True, False, True, True]]
new = c[cut]
#new= [[], [{'x': 3, 'y': 3}, {'x': 3, 'y': 5}], [], [{'x': 5, 'y': 8}, {'x': 6, 'y': 8}, {'x': 6, 'y': 9}]]
new_i = i[cut]
#new_i= [[], [{'x': 0, 'y': 0}, {'x': 0, 'y': 1}], [], [{'x': 1, 'y': 0}, {'x': 2, 'y': 0}, {'x': 2, 'y': 1}]]
It is possible that pairs with the same element from a but different elements from b survive the cut. (e.g. {'x': 3, 'y': 3} and {'x': 3, 'y': 5})
My goal is to group those pairs with the same element from a together and therefore reshape the new array into:
new = [[], [{'x': 3, 'y': [3, 5]}], [], [{'x': 5, 'y': 8}, {'x': 6, 'y': [8, 9]}]]
My only idea how to achieve this is to create a list of the indexes from a that are still present after the cut by using new_i:
i = new_i['x']
#i= [[], [0, 0], [], [1, 2, 2]]
However, I need a unique version of this list to make every index appear only once. This could be achieved with np.unique() in NumPy. But doesn't work in awkward1:
np.unique(i)
<__array_function__ internals> in unique(*args, **kwargs)
TypeError: no implementation found for 'numpy.unique' on types that implement __array_function__: [<class 'awkward1.highlevel.Array'>]
My question:
Is their a np.unique() equivalent in awkward1 and/or would you recommend a different approach to my problem?
Okay, I still don't know how to use np.unique() on my arrays, but I found a solution for my own problem:
In my previous approach I used the following code to pair up booth arrays.
c = ak.cartesian({'x':a, 'y':b})
#c= [[{'x': 1, 'y': 7}, {'x': 2, 'y': 7}], [{'x': 3, 'y': 3}, {'x': 3, 'y': 5}], [], [{'x': 4, 'y': 8}, {'x': 4, 'y': 9}, {'x': 5, 'y': 8}, {'x': 5, 'y': 9}, {'x': 6, 'y': 8}, {'x': 6, 'y': 9}]]
However, with the nested = True parameter from ak.cartesian() I get a list grouped by the elements of a:
c = ak.cartesian({'x':a, 'y':b}, axis = 1, nested = True)
#c= [[[{'x': 1, 'y': 7}], [{'x': 2, 'y': 7}]], [[{'x': 3, 'y': 3}, {'x': 3, 'y': 5}]], [], [[{'x': 4, 'y': 8}, {'x': 4, 'y': 9}], [{'x': 5, 'y': 8}, {'x': 5, 'y': 9}], [{'x': 6, 'y': 8}, {'x': 6, 'y': 9}]]]
After the cut I end up with:
new = c[cut]
#new= [[[], []], [[{'x': 3, 'y': 3}, {'x': 3, 'y': 5}]], [], [[], [{'x': 5, 'y': 8}], [{'x': 6, 'y': 8}, {'x': 6, 'y': 9}]]]
I extract the y values and reduce the most inner layer of the nested lists of new to only one element:
y = new['y']
#y= [[[], []], [[3, 5]], [], [[], [8], [8, 9]]]
new = ak.firsts(new, axis = 2)
#new= [[None, None], [{'x': 3, 'y': 3}], [], [None, {'x': 5, 'y': 8}, {'x': 6, 'y': 8}]]
(I tried to use ak.firsts() with axis = -1 but it seems to be not implemented yet.)
Now every most inner entry in new belongs to exactly one element from a. By replacing the current y of new with the previously extracted y I end up with my desired result:
new['y'] = y
#new= [[None, None], [{'x': 3, 'y': [3, 5]}], [], [None, {'x': 5, 'y': [8]}, {'x': 6, 'y': [8, 9]}]]
Anyway, should you know a better solution, I'd be pleased to hear it.
My question is somewhat similar to this question: https://codereview.stackexchange.com/questions/175079/removing-key-value-pairs-in-list-of-dicts. Essentially, I have a list of dictionaries, and I want to remove duplicates from the list based on the unique combination of two (or more) keys within each dictionary.
Suppose I have the following list of dictionaries:
some_list_of_dicts = [
{'a': 1, 'b': 1, 'c': 1, 'd': 2, 'e': 4},
{'a': 1, 'b': 1, 'c': 1, 'd': 5, 'e': 1},
{'a': 1, 'b': 1, 'c': 1, 'd': 7, 'e': 8},
{'a': 1, 'b': 1, 'c': 1, 'd': 9, 'e': 6},
{'a': 1, 'b': 1, 'c': 2, 'd': 2, 'e': 3},
{'a': 1, 'b': 1, 'c': 3, 'd': 2, 'e': 3},
{'a': 1, 'b': 1, 'c': 4, 'd': 2, 'e': 3}
]
And let's suppose the combination of a, b, and c have to be unique; any other values can be whatever they want, but the combination of these three must be unique to this list. I would want to take whichever unique combo of a, b, and c came first, keep that, and discard everything else where that combination is the same.
The new list, after running it through some remove_duplicates function would look like this:
new_list = [
{'a': 1, 'b': 1, 'c': 1, 'd': 2, 'e': 4},
{'a': 1, 'b': 1, 'c': 2, 'd': 2, 'e': 3},
{'a': 1, 'b': 1, 'c': 3, 'd': 2, 'e': 3},
{'a': 1, 'b': 1, 'c': 4, 'd': 2, 'e': 3}
]
I've only managed to come up with this:
def remove_duplicates(old_list):
uniqueness_check_list = []
new_list = []
for item in old_list:
# The unique combination is 'a', 'b', and 'c'
uniqueness_check = "{}{}{}".format(
item["a"], item["b"], item["c"]
)
if uniqueness_check not in uniqueness_check_list:
new_list.append(item)
uniqueness_check_list.append(uniqueness_check)
return new_list
But this doesn't feel very Pythonic. It also has the problem that I've hardcoded in the function which keys have to be unique; it would be better if I could specify that as an argument to the function itself, but again, not sure what's the most elegant way to do this.
You can use a dict comprehension to construct a dict from the list of dicts in the reversed order so that the values of the first of any unique combinations would take precedence. Use operator.itemgetter to get the unique keys as a tuple. Reverse again in the end for the original order:
from operator import itemgetter
list({itemgetter('a', 'b', 'c')(d): d for d in reversed(some_list_of_dicts)}.values())[::-1]
This returns:
[{'a': 1, 'b': 1, 'c': 1, 'd': 2, 'e': 4},
{'a': 1, 'b': 1, 'c': 2, 'd': 2, 'e': 3},
{'a': 1, 'b': 1, 'c': 3, 'd': 2, 'e': 3},
{'a': 1, 'b': 1, 'c': 4, 'd': 2, 'e': 3}]
With the help of a function to keep track of duplicates, you can use some list comprehension:
def remove_duplicates(old_list, cols=('a', 'b', 'c')):
duplicates = set()
def is_duplicate(item):
duplicate = item in duplicates
duplicates.add(item)
return duplicate
return [x for x in old_list if not is_duplicate(tuple([x[col] for col in cols]))]
To use:
>>> remove_duplicates(some_list_of_dicts)
[
{'a': 1, 'c': 1, 'b': 1, 'e': 4, 'd': 2},
{'a': 1, 'c': 2, 'b': 1, 'e': 3, 'd': 2},
{'a': 1, 'c': 3, 'b': 1, 'e': 3, 'd': 2},
{'a': 1, 'c': 4, 'b': 1, 'e': 3, 'd': 2}
]
You can also provide different columns to key on:
>>> remove_duplicates(some_list_of_dicts, cols=('a', 'd'))
[
{'a': 1, 'c': 1, 'b': 1, 'e': 4, 'd': 2},
{'a': 1, 'c': 1, 'b': 1, 'e': 1, 'd': 5},
{'a': 1, 'c': 1, 'b': 1, 'e': 8, 'd': 7},
{'a': 1, 'c': 1, 'b': 1, 'e': 6, 'd': 9}
]
I have a python dictionary like this example:
small example:
dict = {'chr2:173370685-173370692': 'TACCAAG', 'chr5:118309829-118309836': 'TCTCCTT', 'chr12:104659651-104659658': 'GACCAAA'}
I only need the value part of every item which is a sequence of letters and the letters are A, T, C or G and also the length of each sequence is 7 so, for every sequence of letters there are 7 positions. I want to get the frequency of the 4 mentioned letters in every position (we have 7 positions). for every position I will make a dictionary in which the letters are key and the frequency of every letter is value. and at the end I want to make a dictionary for all seven positions and the fist dictionary would be the value of the final dictionary.
here is the expected output for the small example:
expected output:
final = {one: {'T': 2, 'A': 1, 'C': 0, 'G': 0}, two: {'T': 0, 'A': 2, 'C': 1, 'G': 0}, three: {'T': 1, 'A': 0, 'C': 2, 'G': 0}, four: {'T': 0, 'A': 0, 'C': 3, 'G': 0}, five: {'T': 0, 'A': 2, 'C': 1, 'G': 0}, six: {'T': 1, 'A': 2, 'C': 0, 'G': 0}, seven: {'T': 1, 'A': 1, 'C': 0, 'G': 1}}
to get this output I wrote a code in python but it does not return what exactly I want. do you know how to fix the following code?
one=[]
two=[]
three=[]
four=[]
five=[]
six=[]
seven=[]
mylist = dict.values()
for threeq in mylist:
one.append(threeq[0])
two.append(threeq[1])
three.append(threeq[2])
four.append(threeq[3])
five.append(threeq[4])
six.append(threeq[5])
seven.append(threeq[6])
from collections import Counter
one=Counter(one)
two=Counter(two)
three=Counter(three)
four=Counter(four)
five=Counter(five)
six=Counter(six)
seven=Counter(seven)
Here is a way to do it, using Counter:
from collections import Counter
data = {'chr2:173370685-173370692': 'TACCAAG', 'chr5:118309829-118309836': 'TCTCCTT', 'chr12:104659651-104659658': 'GACCAAA'}
out = {i:Counter(col) for i, col in enumerate(zip(*(data.values()))) }
# we can add the missing keys whose count is 0:
for count in out.values():
count.update(dict.fromkeys('ATGC', 0))
print(out)
# {0: Counter({'T': 2, 'G': 1, 'A': 0, 'C': 0}), 1: Counter({'A': 2, 'C': 1, 'T': 0, 'G': 0}),
# 2: Counter({'C': 2, 'T': 1, 'A': 0, 'G': 0}), 3: Counter({'C': 3, 'A': 0, 'T': 0, 'G': 0}),
# 4: Counter({'A': 2, 'C': 1, 'T': 0, 'G': 0}), 5: Counter({'A': 2, 'T': 1, 'G': 0, 'C': 0}),
# 6: Counter({'G': 1, 'T': 1, 'A': 1, 'C': 0})}
I left the original indices as integers, it's probably easier to use them than strings like 'one', 'two'... But if you really want to:
numbers_as_strings = ['one', 'two', 'three', 'four', 'five', 'six', 'seven']
out = {numbers_as_strings[key]:value for key, value in out.items()}
print(out)
# {'one': Counter({'T': 2, 'G': 1, 'A': 0, 'C': 0}),
# 'two': Counter({'A': 2, 'C': 1, 'T': 0, 'G': 0}) ....
Try this:
values = list(dict.values())
r = {}
for i in range(7):
r[i+1] = {'T': 0, 'A': 0, 'C': 0, 'G': 0}
for v in values:
r[i+1][v[i]] += 1
dict = {'chr2:173370685-173370692': 'TACCAAG', 'chr5:118309829-118309836': 'TCTCCTT', 'chr12:104659651-104659658': 'GACCAAA'}
options=['T','A','C','G']
innerdicts=['one','two','three','four','five','six','seven']
def getposcount(idx,letter,dict):
count=0
for v in dict.values():
if v[idx]==letter:
count+=1
return count
d = {x:{y:getposcount(innerdicts.index(x),y,dict) for y in options} for x in innerdicts}
print(d)
Output
{'six': {'T': 1, 'A': 2, 'G': 0, 'C': 0}, 'one': {'T': 2, 'A': 0, 'G': 1, 'C': 0}, 'two': {'T': 0, 'A': 2, 'G': 0, 'C': 1}, 'five': {'T': 0, 'A': 2, 'G': 0, 'C': 1}, 'three': {'T': 1, 'A': 0, 'G': 0, 'C': 2}, 'seven': {'T': 1, 'A': 1, 'G': 1, 'C': 0}, 'four': {'T': 0, 'A': 0, 'G': 0, 'C': 3}}
If you are willing to accept the integers as keys, you can do:
from collections import Counter
def counts_with_zero(count, keys='TACG'):
return {key: count.get(key, 0) for key in keys}
d = {'chr2:173370685-173370692': 'TACCAAG', 'chr5:118309829-118309836': 'TCTCCTT',
'chr12:104659651-104659658': 'GACCAAA'}
values = list(d.values())
result = {i: counts_with_zero(Counter(column)) for i, column in enumerate(zip(*values), 1)}
print(result)
Output
{1: {'A': 0, 'C': 0, 'G': 1, 'T': 2},
2: {'A': 2, 'C': 1, 'G': 0, 'T': 0},
3: {'A': 0, 'C': 2, 'G': 0, 'T': 1},
4: {'A': 0, 'C': 3, 'G': 0, 'T': 0},
5: {'A': 2, 'C': 1, 'G': 0, 'T': 0},
6: {'A': 2, 'C': 0, 'G': 0, 'T': 1},
7: {'A': 1, 'C': 0, 'G': 1, 'T': 1}}
I have a list of dictionary items
[{'x': 0, 'y': 0}, {'x': 1, 'y': 0}, {'x': 2, 'y': 2}]
I want to have an array of "array of dictionaries" with all the maximum permutation order of the list for example for the above array it would be (3 factorial ways)
[[{'x': 0, 'y': 0}, {'x': 1, 'y': 0}, {'x': 2, 'y': 2}],
[{'x': 0, 'y': 0}, {'x': 2, 'y': 2}, {'x': 1, 'y': 0}],
[{'x': 1, 'y': 0}, {'x': 0, 'y': 0}, {'x': 2, 'y': 2}],
[{'x': 1, 'y': 0}, {'x': 2, 'y': 2}, {'x': 0, 'y': 0}],
[{'x': 2, 'y': 2}, {'x': 1, 'y': 0}, {'x': 0, 'y': 0}],
[{'x': 2, 'y': 2}, {'x': 0, 'y': 0}, {'x': 1, 'y': 0}]]
itertools can do permutations
#!python2
import itertools
yourlist = [{'x': 0, 'y': 0}, {'x': 1, 'y': 0}, {'x': 2, 'y': 2}]
for seq in itertools.permutations(yourlist):
print seq
'''
({'y': 0, 'x': 0}, {'y': 0, 'x': 1}, {'y': 2, 'x': 2})
({'y': 0, 'x': 0}, {'y': 2, 'x': 2}, {'y': 0, 'x': 1})
({'y': 0, 'x': 1}, {'y': 0, 'x': 0}, {'y': 2, 'x': 2})
({'y': 0, 'x': 1}, {'y': 2, 'x': 2}, {'y': 0, 'x': 0})
({'y': 2, 'x': 2}, {'y': 0, 'x': 0}, {'y': 0, 'x': 1})
({'y': 2, 'x': 2}, {'y': 0, 'x': 1}, {'y': 0, 'x': 0})
'''
Despite the comments, if you are still messed with how to solve your issue, consider the following.
Strategy: Make use of permutations from itertoolswhich returns a list of tuples in this case. Then, iterating through to convert list of tuples to list of lists to match with your required output.
Here is how you could do:
>>> import itertools
>>> lst = [{'x': 0, 'y': 0}, {'x': 1, 'y': 0}, {'x': 2, 'y': 2}]
>>> [list(elem) for elem in list(itertools.permutations(lst))]
[[{'x': 0, 'y': 0}, {'x': 1, 'y': 0}, {'x': 2, 'y': 2}],
[{'x': 0, 'y': 0}, {'x': 2, 'y': 2}, {'x': 1, 'y': 0}],
[{'x': 1, 'y': 0}, {'x': 0, 'y': 0}, {'x': 2, 'y': 2}],
[{'x': 1, 'y': 0}, {'x': 2, 'y': 2}, {'x': 0, 'y': 0}],
[{'x': 2, 'y': 2}, {'x': 0, 'y': 0}, {'x': 1, 'y': 0}],
[{'x': 2, 'y': 2}, {'x': 1, 'y': 0}, {'x': 0, 'y': 0}]]
Given a string such as "xyz", I would like to generate all dictionaries of the form:
{"x": vx, "y": vy, "z": vz}
where vx, vy, vz are integers between 1 and 5.
So in the above case, there are 125 such dictionaries. But the string can have variable length.
What is a Pythonic way to do this?
I'm positive this is a duplicate but I can't find a good one right now, so I'll answer and make it community wiki. Using itertools.product:
>>> from itertools import product
>>> s = "xyz"
>>> [dict(zip(s,v)) for v in product(range(1,6),repeat=len(s))]
[{'y': 1, 'x': 1, 'z': 1}, {'y': 1, 'x': 1, 'z': 2}, {'y': 1, 'x': 1, 'z': 3}, {'y': 1, 'x': 1, 'z': 4}, {'y': 1, 'x': 1, 'z': 5}, {'y': 2, 'x': 1, 'z': 1}, {'y': 2, 'x': 1, 'z': 2}, {'y': 2, 'x': 1, 'z': 3}, {'y': 2, 'x': 1, 'z': 4}, {'y': 2, 'x': 1, 'z': 5}, {'y': 3, 'x': 1, 'z': 1}, {'y': 3, 'x': 1, 'z': 2}, {'y': 3, 'x': 1, 'z': 3}, {'y': 3, 'x': 1, 'z': 4}, {'y': 3, 'x': 1, 'z': 5}, {'y': 4, 'x': 1, 'z': 1}, {'y': 4, 'x': 1, 'z': 2}, {'y': 4, 'x': 1, 'z': 3}, {'y': 4, 'x': 1, 'z': 4}, {'y': 4, 'x': 1, 'z': 5}, {'y': 5, 'x': 1, 'z': 1}, {'y': 5, 'x': 1, 'z': 2}, {'y': 5, 'x': 1, 'z': 3}, {'y': 5, 'x': 1, 'z': 4}, {'y': 5, 'x': 1, 'z': 5}, {'y': 1, 'x': 2, 'z': 1}, {'y': 1, 'x': 2, 'z': 2}, {'y': 1, 'x': 2, 'z': 3}, {'y': 1, 'x': 2, 'z': 4}, {'y': 1, 'x': 2, 'z': 5}, {'y': 2, 'x': 2, 'z': 1}, {'y': 2, 'x': 2, 'z': 2}, {'y': 2, 'x': 2, 'z': 3}, {'y': 2, 'x': 2, 'z': 4}, {'y': 2, 'x': 2, 'z': 5}, {'y': 3, 'x': 2, 'z': 1}, {'y': 3, 'x': 2, 'z': 2}, {'y': 3, 'x': 2, 'z': 3}, {'y': 3, 'x': 2, 'z': 4}, {'y': 3, 'x': 2, 'z': 5}, {'y': 4, 'x': 2, 'z': 1}, {'y': 4, 'x': 2, 'z': 2}, {'y': 4, 'x': 2, 'z': 3}, {'y': 4, 'x': 2, 'z': 4}, {'y': 4, 'x': 2, 'z': 5}, {'y': 5, 'x': 2, 'z': 1}, {'y': 5, 'x': 2, 'z': 2}, {'y': 5, 'x': 2, 'z': 3}, {'y': 5, 'x': 2, 'z': 4}, {'y': 5, 'x': 2, 'z': 5}, {'y': 1, 'x': 3, 'z': 1}, {'y': 1, 'x': 3, 'z': 2}, {'y': 1, 'x': 3, 'z': 3}, {'y': 1, 'x': 3, 'z': 4}, {'y': 1, 'x': 3, 'z': 5}, {'y': 2, 'x': 3, 'z': 1}, {'y': 2, 'x': 3, 'z': 2}, {'y': 2, 'x': 3, 'z': 3}, {'y': 2, 'x': 3, 'z': 4}, {'y': 2, 'x': 3, 'z': 5}, {'y': 3, 'x': 3, 'z': 1}, {'y': 3, 'x': 3, 'z': 2}, {'y': 3, 'x': 3, 'z': 3}, {'y': 3, 'x': 3, 'z': 4}, {'y': 3, 'x': 3, 'z': 5}, {'y': 4, 'x': 3, 'z': 1}, {'y': 4, 'x': 3, 'z': 2}, {'y': 4, 'x': 3, 'z': 3}, {'y': 4, 'x': 3, 'z': 4}, {'y': 4, 'x': 3, 'z': 5}, {'y': 5, 'x': 3, 'z': 1}, {'y': 5, 'x': 3, 'z': 2}, {'y': 5, 'x': 3, 'z': 3}, {'y': 5, 'x': 3, 'z': 4}, {'y': 5, 'x': 3, 'z': 5}, {'y': 1, 'x': 4, 'z': 1}, {'y': 1, 'x': 4, 'z': 2}, {'y': 1, 'x': 4, 'z': 3}, {'y': 1, 'x': 4, 'z': 4}, {'y': 1, 'x': 4, 'z': 5}, {'y': 2, 'x': 4, 'z': 1}, {'y': 2, 'x': 4, 'z': 2}, {'y': 2, 'x': 4, 'z': 3}, {'y': 2, 'x': 4, 'z': 4}, {'y': 2, 'x': 4, 'z': 5}, {'y': 3, 'x': 4, 'z': 1}, {'y': 3, 'x': 4, 'z': 2}, {'y': 3, 'x': 4, 'z': 3}, {'y': 3, 'x': 4, 'z': 4}, {'y': 3, 'x': 4, 'z': 5}, {'y': 4, 'x': 4, 'z': 1}, {'y': 4, 'x': 4, 'z': 2}, {'y': 4, 'x': 4, 'z': 3}, {'y': 4, 'x': 4, 'z': 4}, {'y': 4, 'x': 4, 'z': 5}, {'y': 5, 'x': 4, 'z': 1}, {'y': 5, 'x': 4, 'z': 2}, {'y': 5, 'x': 4, 'z': 3}, {'y': 5, 'x': 4, 'z': 4}, {'y': 5, 'x': 4, 'z': 5}, {'y': 1, 'x': 5, 'z': 1}, {'y': 1, 'x': 5, 'z': 2}, {'y': 1, 'x': 5, 'z': 3}, {'y': 1, 'x': 5, 'z': 4}, {'y': 1, 'x': 5, 'z': 5}, {'y': 2, 'x': 5, 'z': 1}, {'y': 2, 'x': 5, 'z': 2}, {'y': 2, 'x': 5, 'z': 3}, {'y': 2, 'x': 5, 'z': 4}, {'y': 2, 'x': 5, 'z': 5}, {'y': 3, 'x': 5, 'z': 1}, {'y': 3, 'x': 5, 'z': 2}, {'y': 3, 'x': 5, 'z': 3}, {'y': 3, 'x': 5, 'z': 4}, {'y': 3, 'x': 5, 'z': 5}, {'y': 4, 'x': 5, 'z': 1}, {'y': 4, 'x': 5, 'z': 2}, {'y': 4, 'x': 5, 'z': 3}, {'y': 4, 'x': 5, 'z': 4}, {'y': 4, 'x': 5, 'z': 5}, {'y': 5, 'x': 5, 'z': 1}, {'y': 5, 'x': 5, 'z': 2}, {'y': 5, 'x': 5, 'z': 3}, {'y': 5, 'x': 5, 'z': 4}, {'y': 5, 'x': 5, 'z': 5}]
>>> len(_)
125
Note that we haven't hardcoded the length of the string.