我有一个有n个键的字典,每个键包含一个n个字符串的列表。
我希望遍历字符串的每个组合,产生密钥和与之关联的字符串。
这是一个包含3个键的字典示例,但我想概括为带有n个键的字典。
dict = {'key1':['str0','str1','str2','strn'],'key2':['apples','bananas','mangos'],'key3':['spam','eggs','more spam']}
for str1 in dict['key1']:
for str2 in dict['key2']:
for str3 in dict['key3']:
print 'key1'+"."+str1,'key2'+"."+str2,'key3'+"."+str3
请回答这个问题时,你能描述一下这个问题是如何解决的,因为我对python有了新的认识并且还不知道所有可用的工具!
预期产出:
key1.str0 key2.apples key3.spam
key1.str0 key2.apples key3.eggs
key1.str0 key2.apples key3.more spam
key1.str0 key2.bananas key3.spam
key1.str0 key2.bananas key3.eggs
...
n维迭代器的预期输出:
key1.str0 key2.apples key3.spam ... keyn.string0
key1.str0 key2.apples key3.spam ... keyn.string1
key1.str0 key2.apples key3.spam ... keyn.string2
...
key1.str0 key2.apples key3.spam ... keyn.stringn
...
答案 0 :(得分:3)
你应该使用itertools.product
,它会执行Cartesian product,这是你要做的事情的名称。
from itertools import product
# don't shadow the built-in name `dict`
d = {'key1': ['str0','str1','str2','strn'], 'key2': ['apples','bananas','mangos'], 'key3': ['spam','eggs','more spam']}
# dicts aren't sorted, but you seem to want key1 -> key2 -> key3 order, so
# let's get a sorted copy of the keys
keys = sorted(d.keys())
# and then get the values in the same order
values = [d[key] for key in keys]
# perform the Cartesian product
# product(*values) means product(values[0], values[1], values[2], ...)
results = product(*values)
# each `result` is something like ('str0', 'apples', 'spam')
for result in results:
# pair up each entry in `result` with its corresponding key
# So, zip(('key1', 'key2', 'key3'), ('str0', 'apples', 'spam'))
# yields (('key1', 'str0'), ('key2', 'apples'), ('key3', 'spam'))
# schematically speaking, anyway
for key, thing in zip(keys, result):
print key + '.' + thing,
print
请注意,我们没有在字典中硬编码密钥的数量。如果您使用collections.OrderedDict
而不是dict
,则可以避免排序。
如果您希望将键附加到其值:
,这是另一个选项from itertools import product
d = {'key1': ['str0','str1','str2','strn'], 'key2': ['apples','bananas','mangos'], 'key3': ['spam','eggs','more spam']}
foo = [[(key, value) for value in d[key]] for key in sorted(d.keys())]
results = product(*foo)
for result in results:
for key, value in result:
print key + '.' + value,
print
在这里,我们构建一个(键,值)元组列表的列表,然后将笛卡尔积应用于列表。这样,键和值之间的关系完全包含在results
中。想想看,这可能比我发布的第一种方式更好。
答案 1 :(得分:1)
您可以使用递归函数:
# make a list of all the keys
keys = list(dict.keys())
def f(keys, dict, depth=0, to_print=[]):
if depth < len(keys):
for item in dict[keys[depth]]:
to_print.append(keys[depth] + '.' + item + ' ')
f(keys, dict, depth + 1, to_print)
del to_print[-1]
else:
# you can format the output as you wish; here i'm just printing the list
print to_print
# call the function
f(keys, dict)
答案 2 :(得分:1)
我想要一个更实用的风格,它与@Shanshin的回答基本相同:
import itertools
from pprint import pprint
def foo(d):
def g(item):
"""create and return key.value1, key.value2, ..., key.valueN iterator
item is a (key, value) dictionary item, assumes value is a sequence/iterator
"""
# associate the key with each value - (key, value0) ... (key, valueN)
kay_vees = itertools.izip(itertools.repeat(item[0]), item[1])
return itertools.imap('.'.join, kay_vees)
# generator that produces n data sets from the dict
a = itertools.imap(g, d.iteritems())
# cartesian product of the datasets
return itertools.product(*a)
用法:
c = list(foo(d))
pprint(c)
for thing in foo(d):
print thing
一旦消耗,迭代器需要重新定义 - foo
将为每次调用返回一个新的迭代器。