繁体   English   中英

列表字典的笛卡尔积 - 有排序

[英]Cartesian product of a dictionary of lists - with sorting

背景

我目前正在使用一种在另一个Stackoverflow帖子中完美演示技术来创建列表字典的笛卡尔积,即:

from itertools import product
def my_product(inp):
    return (dict(zip(inp.keys(), values)) for values in product(*inp.values())

问题

这是我的示例字典, d

d = {
    "letters": ['a', 'b'],
    "numbers": [1, 2, 3],
    "status": ["on", "off"]
}

我遇到的问题是,我想使用这种技术来创建一个生成器。 但是,我想控制某些列表被“扫描”的顺序。 例如,这是我的代码生成的前几次迭代的常见结果:

{"status": "on",  "numbers": 1, "letters": 'a'}
{"status": "off", "numbers": 1, "letters": 'a'}
{"status": "on",  "numbers": 2, "letters": 'a'}
{"status": "off", "numbers": 2, "letters": 'a'}
{"status": "on",  "numbers": 3, "letters": 'a'}
{"status": "off", "numbers": 3, "letters": 'a'}
{"status": "on",  "numbers": 1, "letters": 'b'}
{"status": "off", "numbers": 1, "letters": 'b'}

但是,我需要能够控制产品如何生成这些排列的顺序。 当我切换“状态”的“开”/“关”值时,“馈送”字典的代码具有高“成本”,但是不会因更改“数字”或“字母”元素而受到惩罚。 例如,这将是生成器产生的理想迭代集:

{"letters": 'a', "numbers": 1, "status": "on"}
{"letters": 'a', "numbers": 2, "status": "on"}
{"letters": 'a', "numbers": 3, "status": "on"}
{"letters": 'b', "numbers": 1, "status": "on"}
{"letters": 'b', "numbers": 2, "status": "on"}
{"letters": 'b', "numbers": 3, "status": "on"}
{"letters": 'a', "numbers": 1, "status": "off"}
{"letters": 'a', "numbers": 2, "status": "off"}
{"letters": 'a', "numbers": 3, "status": "off"}
{"letters": 'b', "numbers": 1, "status": "off"}
{"letters": 'b', "numbers": 2, "status": "off"}
{"letters": 'b', "numbers": 3, "status": "off"}

简而言之,我希望能够通过向字典的某些成员显示“首选项”来最小化从一个值到另一个值的转换次数, d


我怎么能做到这一点?


结论

使用接受的答案,我生成了这段代码:


代码清单

#!/usr/bin/env python
from collections import OrderedDict
from itertools import product

d = OrderedDict()
d["status"] = ["on", "off"]
d["letters"] = ["a", "b", "c"]
d["numbers"] = [1, 2, 3, 4]

for i in (dict(zip(inp.keys(), values)) for values in product(*inp.values())):
    print(i)

样本输出

{'status': 'on', 'letters': 'a', 'numbers': 1}
{'status': 'on', 'letters': 'a', 'numbers': 2}
{'status': 'on', 'letters': 'a', 'numbers': 3}
{'status': 'on', 'letters': 'a', 'numbers': 4}
{'status': 'on', 'letters': 'b', 'numbers': 1}
{'status': 'on', 'letters': 'b', 'numbers': 2}
{'status': 'on', 'letters': 'b', 'numbers': 3}
{'status': 'on', 'letters': 'b', 'numbers': 4}
{'status': 'on', 'letters': 'c', 'numbers': 1}
{'status': 'on', 'letters': 'c', 'numbers': 2}
{'status': 'on', 'letters': 'c', 'numbers': 3}
{'status': 'on', 'letters': 'c', 'numbers': 4}
{'status': 'off', 'letters': 'a', 'numbers': 1}
{'status': 'off', 'letters': 'a', 'numbers': 2}
{'status': 'off', 'letters': 'a', 'numbers': 3}
{'status': 'off', 'letters': 'a', 'numbers': 4}
{'status': 'off', 'letters': 'b', 'numbers': 1}
{'status': 'off', 'letters': 'b', 'numbers': 2}
{'status': 'off', 'letters': 'b', 'numbers': 3}
{'status': 'off', 'letters': 'b', 'numbers': 4}
{'status': 'off', 'letters': 'c', 'numbers': 1}
{'status': 'off', 'letters': 'c', 'numbers': 2}
{'status': 'off', 'letters': 'c', 'numbers': 3}
{'status': 'off', 'letters': 'c', 'numbers': 4}

如果您使用的是Python 3.5或更高版本,则可以将status为dict中的第一个键:

d = {
    "status": ["on", "off"],
    "letters": ['a', 'b'],
    "numbers": [1, 2, 3]
}

对于早期版本,请使用collections.OrderedDict代替dict。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM