代码之家  ›  专栏  ›  技术社区  ›  Cloud

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

  •  0
  • Cloud  · 技术社区  · 6 年前

    背景

    我正在使用 technique that is perfectly demonstrated in another Stackoverflow post 创建列表字典的笛卡尔积,即:

    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"}
    

    简而言之,我希望能够通过向字典的某些成员显示“preference”来最小化从一个值到另一个值的转换次数, 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}
    

    1 回复  |  直到 6 年前
        1
  •  3
  •   blhsing    6 年前

    如果您使用的是Python3.5或更高版本,可以 status 你口述的第一个键是:

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

    对于早期版本,使用 collections.OrderedDict 代替口述。