Product of dictionary values

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
9
down vote

favorite












Elements that smell funny: argument unpacking to itertools.product. I'm needing sorted keys (even though I don't care about key order in the final result).



"""
>>> d = 'A': [0, 1, 2],
... 'B': [3, 4],
... 'C': [5, 6, 7]
>>> for element in dict_product(d):
... print(element)
'A': 0, 'B': 3, 'C': 5
'A': 0, 'B': 3, 'C': 6
'A': 0, 'B': 3, 'C': 7
'A': 0, 'B': 4, 'C': 5
'A': 0, 'B': 4, 'C': 6
'A': 0, 'B': 4, 'C': 7
'A': 1, 'B': 3, 'C': 5
'A': 1, 'B': 3, 'C': 6
'A': 1, 'B': 3, 'C': 7
'A': 1, 'B': 4, 'C': 5
'A': 1, 'B': 4, 'C': 6
'A': 1, 'B': 4, 'C': 7
'A': 2, 'B': 3, 'C': 5
'A': 2, 'B': 3, 'C': 6
'A': 2, 'B': 3, 'C': 7
'A': 2, 'B': 4, 'C': 5
'A': 2, 'B': 4, 'C': 6
'A': 2, 'B': 4, 'C': 7

"""

from itertools import product

def dict_product(d):
sorted_keys = sorted(d.keys())
for element in product(*list(d[k] for k in sorted_keys)):
yield dict(zip(sorted_keys, element))


if __name__ == "__main__":
import doctest
doctest.testmod(verbose=True)






share|improve this question





















  • I had the same need a while back.
    – Mathias Ettinger
    Jan 14 at 17:57










  • map(dict, product(*[[(k, v) for v in vv] for k, vv in d.items()]))
    – Gareth Rees
    Jan 14 at 19:53
















up vote
9
down vote

favorite












Elements that smell funny: argument unpacking to itertools.product. I'm needing sorted keys (even though I don't care about key order in the final result).



"""
>>> d = 'A': [0, 1, 2],
... 'B': [3, 4],
... 'C': [5, 6, 7]
>>> for element in dict_product(d):
... print(element)
'A': 0, 'B': 3, 'C': 5
'A': 0, 'B': 3, 'C': 6
'A': 0, 'B': 3, 'C': 7
'A': 0, 'B': 4, 'C': 5
'A': 0, 'B': 4, 'C': 6
'A': 0, 'B': 4, 'C': 7
'A': 1, 'B': 3, 'C': 5
'A': 1, 'B': 3, 'C': 6
'A': 1, 'B': 3, 'C': 7
'A': 1, 'B': 4, 'C': 5
'A': 1, 'B': 4, 'C': 6
'A': 1, 'B': 4, 'C': 7
'A': 2, 'B': 3, 'C': 5
'A': 2, 'B': 3, 'C': 6
'A': 2, 'B': 3, 'C': 7
'A': 2, 'B': 4, 'C': 5
'A': 2, 'B': 4, 'C': 6
'A': 2, 'B': 4, 'C': 7

"""

from itertools import product

def dict_product(d):
sorted_keys = sorted(d.keys())
for element in product(*list(d[k] for k in sorted_keys)):
yield dict(zip(sorted_keys, element))


if __name__ == "__main__":
import doctest
doctest.testmod(verbose=True)






share|improve this question





















  • I had the same need a while back.
    – Mathias Ettinger
    Jan 14 at 17:57










  • map(dict, product(*[[(k, v) for v in vv] for k, vv in d.items()]))
    – Gareth Rees
    Jan 14 at 19:53












up vote
9
down vote

favorite









up vote
9
down vote

favorite











Elements that smell funny: argument unpacking to itertools.product. I'm needing sorted keys (even though I don't care about key order in the final result).



"""
>>> d = 'A': [0, 1, 2],
... 'B': [3, 4],
... 'C': [5, 6, 7]
>>> for element in dict_product(d):
... print(element)
'A': 0, 'B': 3, 'C': 5
'A': 0, 'B': 3, 'C': 6
'A': 0, 'B': 3, 'C': 7
'A': 0, 'B': 4, 'C': 5
'A': 0, 'B': 4, 'C': 6
'A': 0, 'B': 4, 'C': 7
'A': 1, 'B': 3, 'C': 5
'A': 1, 'B': 3, 'C': 6
'A': 1, 'B': 3, 'C': 7
'A': 1, 'B': 4, 'C': 5
'A': 1, 'B': 4, 'C': 6
'A': 1, 'B': 4, 'C': 7
'A': 2, 'B': 3, 'C': 5
'A': 2, 'B': 3, 'C': 6
'A': 2, 'B': 3, 'C': 7
'A': 2, 'B': 4, 'C': 5
'A': 2, 'B': 4, 'C': 6
'A': 2, 'B': 4, 'C': 7

"""

from itertools import product

def dict_product(d):
sorted_keys = sorted(d.keys())
for element in product(*list(d[k] for k in sorted_keys)):
yield dict(zip(sorted_keys, element))


if __name__ == "__main__":
import doctest
doctest.testmod(verbose=True)






share|improve this question













Elements that smell funny: argument unpacking to itertools.product. I'm needing sorted keys (even though I don't care about key order in the final result).



"""
>>> d = 'A': [0, 1, 2],
... 'B': [3, 4],
... 'C': [5, 6, 7]
>>> for element in dict_product(d):
... print(element)
'A': 0, 'B': 3, 'C': 5
'A': 0, 'B': 3, 'C': 6
'A': 0, 'B': 3, 'C': 7
'A': 0, 'B': 4, 'C': 5
'A': 0, 'B': 4, 'C': 6
'A': 0, 'B': 4, 'C': 7
'A': 1, 'B': 3, 'C': 5
'A': 1, 'B': 3, 'C': 6
'A': 1, 'B': 3, 'C': 7
'A': 1, 'B': 4, 'C': 5
'A': 1, 'B': 4, 'C': 6
'A': 1, 'B': 4, 'C': 7
'A': 2, 'B': 3, 'C': 5
'A': 2, 'B': 3, 'C': 6
'A': 2, 'B': 3, 'C': 7
'A': 2, 'B': 4, 'C': 5
'A': 2, 'B': 4, 'C': 6
'A': 2, 'B': 4, 'C': 7

"""

from itertools import product

def dict_product(d):
sorted_keys = sorted(d.keys())
for element in product(*list(d[k] for k in sorted_keys)):
yield dict(zip(sorted_keys, element))


if __name__ == "__main__":
import doctest
doctest.testmod(verbose=True)








share|improve this question












share|improve this question




share|improve this question








edited Jan 14 at 23:15









Jamal♦

30.1k11114225




30.1k11114225









asked Jan 14 at 16:03









MikeRand

1644




1644











  • I had the same need a while back.
    – Mathias Ettinger
    Jan 14 at 17:57










  • map(dict, product(*[[(k, v) for v in vv] for k, vv in d.items()]))
    – Gareth Rees
    Jan 14 at 19:53
















  • I had the same need a while back.
    – Mathias Ettinger
    Jan 14 at 17:57










  • map(dict, product(*[[(k, v) for v in vv] for k, vv in d.items()]))
    – Gareth Rees
    Jan 14 at 19:53















I had the same need a while back.
– Mathias Ettinger
Jan 14 at 17:57




I had the same need a while back.
– Mathias Ettinger
Jan 14 at 17:57












map(dict, product(*[[(k, v) for v in vv] for k, vv in d.items()]))
– Gareth Rees
Jan 14 at 19:53




map(dict, product(*[[(k, v) for v in vv] for k, vv in d.items()]))
– Gareth Rees
Jan 14 at 19:53










1 Answer
1






active

oldest

votes

















up vote
11
down vote



accepted










You can use the fact that d.keys() and d.values() are always aligned. This gets rid of both the awkward way of constructing the values as well as the sorting of the keys.



def dict_product(d):
keys = d.keys()
for element in product(*d.values()):
yield dict(zip(keys, element))


The assignment of keys is not strictly necessary, but it avoids the look-up every loop iteration.




Note that list(d[k] for k in sorted_keys) should have been written as a list comprehension directly, instead of calling list on a generator comprehension. So [d[k] for k in sorted_keys].




Your doctest might fail in Python 2 or in Python implementations other than cPython. This is because only recently have dictionary keys become ordered (by insertion time) in (c)Python 3. This is still an implementation detail and not something you should rely upon. Since doctest performs a string comparison, it does not notice that the objects are actually the same.



The only way around this, at least the only one I can see, is to use a more sophisticated testing framework, like unittest. This comes with more code overhead, though.






share|improve this answer























  • And if you are going to invest in something like unittest, go straight to pytest. Better in basically every way.
    – Stephen Rauch
    Jan 14 at 22:45







  • 2




    To make this work with doctest, one can (a) use OrderedDict on input and pprint (which sorts dictionaries) on output or (b) somewhat awkwardly construct a set of frozensets and compare it to an expected value.
    – flornquake
    Jan 14 at 23:32











Your Answer




StackExchange.ifUsing("editor", function ()
return StackExchange.using("mathjaxEditing", function ()
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
);
);
, "mathjax-editing");

StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "196"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: false,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);








 

draft saved


draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f185093%2fproduct-of-dictionary-values%23new-answer', 'question_page');

);

Post as a guest






























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
11
down vote



accepted










You can use the fact that d.keys() and d.values() are always aligned. This gets rid of both the awkward way of constructing the values as well as the sorting of the keys.



def dict_product(d):
keys = d.keys()
for element in product(*d.values()):
yield dict(zip(keys, element))


The assignment of keys is not strictly necessary, but it avoids the look-up every loop iteration.




Note that list(d[k] for k in sorted_keys) should have been written as a list comprehension directly, instead of calling list on a generator comprehension. So [d[k] for k in sorted_keys].




Your doctest might fail in Python 2 or in Python implementations other than cPython. This is because only recently have dictionary keys become ordered (by insertion time) in (c)Python 3. This is still an implementation detail and not something you should rely upon. Since doctest performs a string comparison, it does not notice that the objects are actually the same.



The only way around this, at least the only one I can see, is to use a more sophisticated testing framework, like unittest. This comes with more code overhead, though.






share|improve this answer























  • And if you are going to invest in something like unittest, go straight to pytest. Better in basically every way.
    – Stephen Rauch
    Jan 14 at 22:45







  • 2




    To make this work with doctest, one can (a) use OrderedDict on input and pprint (which sorts dictionaries) on output or (b) somewhat awkwardly construct a set of frozensets and compare it to an expected value.
    – flornquake
    Jan 14 at 23:32















up vote
11
down vote



accepted










You can use the fact that d.keys() and d.values() are always aligned. This gets rid of both the awkward way of constructing the values as well as the sorting of the keys.



def dict_product(d):
keys = d.keys()
for element in product(*d.values()):
yield dict(zip(keys, element))


The assignment of keys is not strictly necessary, but it avoids the look-up every loop iteration.




Note that list(d[k] for k in sorted_keys) should have been written as a list comprehension directly, instead of calling list on a generator comprehension. So [d[k] for k in sorted_keys].




Your doctest might fail in Python 2 or in Python implementations other than cPython. This is because only recently have dictionary keys become ordered (by insertion time) in (c)Python 3. This is still an implementation detail and not something you should rely upon. Since doctest performs a string comparison, it does not notice that the objects are actually the same.



The only way around this, at least the only one I can see, is to use a more sophisticated testing framework, like unittest. This comes with more code overhead, though.






share|improve this answer























  • And if you are going to invest in something like unittest, go straight to pytest. Better in basically every way.
    – Stephen Rauch
    Jan 14 at 22:45







  • 2




    To make this work with doctest, one can (a) use OrderedDict on input and pprint (which sorts dictionaries) on output or (b) somewhat awkwardly construct a set of frozensets and compare it to an expected value.
    – flornquake
    Jan 14 at 23:32













up vote
11
down vote



accepted







up vote
11
down vote



accepted






You can use the fact that d.keys() and d.values() are always aligned. This gets rid of both the awkward way of constructing the values as well as the sorting of the keys.



def dict_product(d):
keys = d.keys()
for element in product(*d.values()):
yield dict(zip(keys, element))


The assignment of keys is not strictly necessary, but it avoids the look-up every loop iteration.




Note that list(d[k] for k in sorted_keys) should have been written as a list comprehension directly, instead of calling list on a generator comprehension. So [d[k] for k in sorted_keys].




Your doctest might fail in Python 2 or in Python implementations other than cPython. This is because only recently have dictionary keys become ordered (by insertion time) in (c)Python 3. This is still an implementation detail and not something you should rely upon. Since doctest performs a string comparison, it does not notice that the objects are actually the same.



The only way around this, at least the only one I can see, is to use a more sophisticated testing framework, like unittest. This comes with more code overhead, though.






share|improve this answer















You can use the fact that d.keys() and d.values() are always aligned. This gets rid of both the awkward way of constructing the values as well as the sorting of the keys.



def dict_product(d):
keys = d.keys()
for element in product(*d.values()):
yield dict(zip(keys, element))


The assignment of keys is not strictly necessary, but it avoids the look-up every loop iteration.




Note that list(d[k] for k in sorted_keys) should have been written as a list comprehension directly, instead of calling list on a generator comprehension. So [d[k] for k in sorted_keys].




Your doctest might fail in Python 2 or in Python implementations other than cPython. This is because only recently have dictionary keys become ordered (by insertion time) in (c)Python 3. This is still an implementation detail and not something you should rely upon. Since doctest performs a string comparison, it does not notice that the objects are actually the same.



The only way around this, at least the only one I can see, is to use a more sophisticated testing framework, like unittest. This comes with more code overhead, though.







share|improve this answer















share|improve this answer



share|improve this answer








edited Jan 14 at 22:54


























answered Jan 14 at 16:15









Graipher

20.5k43081




20.5k43081











  • And if you are going to invest in something like unittest, go straight to pytest. Better in basically every way.
    – Stephen Rauch
    Jan 14 at 22:45







  • 2




    To make this work with doctest, one can (a) use OrderedDict on input and pprint (which sorts dictionaries) on output or (b) somewhat awkwardly construct a set of frozensets and compare it to an expected value.
    – flornquake
    Jan 14 at 23:32

















  • And if you are going to invest in something like unittest, go straight to pytest. Better in basically every way.
    – Stephen Rauch
    Jan 14 at 22:45







  • 2




    To make this work with doctest, one can (a) use OrderedDict on input and pprint (which sorts dictionaries) on output or (b) somewhat awkwardly construct a set of frozensets and compare it to an expected value.
    – flornquake
    Jan 14 at 23:32
















And if you are going to invest in something like unittest, go straight to pytest. Better in basically every way.
– Stephen Rauch
Jan 14 at 22:45





And if you are going to invest in something like unittest, go straight to pytest. Better in basically every way.
– Stephen Rauch
Jan 14 at 22:45





2




2




To make this work with doctest, one can (a) use OrderedDict on input and pprint (which sorts dictionaries) on output or (b) somewhat awkwardly construct a set of frozensets and compare it to an expected value.
– flornquake
Jan 14 at 23:32





To make this work with doctest, one can (a) use OrderedDict on input and pprint (which sorts dictionaries) on output or (b) somewhat awkwardly construct a set of frozensets and compare it to an expected value.
– flornquake
Jan 14 at 23:32













 

draft saved


draft discarded


























 


draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f185093%2fproduct-of-dictionary-values%23new-answer', 'question_page');

);

Post as a guest













































































Popular posts from this blog

Chat program with C++ and SFML

Function to Return a JSON Like Objects Using VBA Collections and Arrays

Will my employers contract hold up in court?