【问题标题】:Conditionally enumerate through all elements of a dict in python有条件地枚举python中dict的所有元素
【发布时间】:2017-10-26 14:40:01
【问题描述】:

我有一个这样的字典:

config = {
          'CONF_A': ['a1', 'a2', 'a3'],
          'CONF_B': ['b1', 'b2'],
          'CONF_C': {
                     'CONF_C1': ['c1'],
                     'CONF_C2': ['c21','c22']
                    }
          }

我需要枚举 CONF_A 和 CONF_B 的所有值,首先使用 CONF_C1 中的所有值,然后使用 CONF_C2 中的所有值。例如:

('a1', 'b1', 'c1')
('a1', 'b2', 'c1')
('a2', 'b1', 'c1')
('a2', 'b2', 'c1')
('a3', 'b1', 'c1')
('a3', 'b2', 'c1')
.... same for 'c21'
.... same for 'c22'

我也需要拥有这些的钥匙。我可以为仅包含 CONF_A 和 CONF_B 的配置获取此信息(见下文),但我不确定如何枚举每个 CONF_C 元素。

>>> for x in itertools.product(*conf.itervalues()):
        for k, v in itertools.izip(conf,x):
            print k,v
...        
    CONF_A a1
    CONF_B b1
    CONF_A a1
    CONF_B b2
    CONF_A a2
    CONF_B b1
    CONF_A a2
    CONF_B b2
    CONF_A a3
    CONF_B b1
    CONF_A a3
    CONF_B b2

注意CONF_C 元素的键应该是 'CONF_C1' 和 'CONF_C2'

----编辑----

@Patrick.Haugh 为问题的第一部分提供了这个答案:

 for x in product(config['CONF_A'], config['CONF_B'], chain.from_iterable(config['CONF_C'].values())):

这适用于获取笛卡尔积,但是我仍然需要重新输入密钥。当我执行以下操作时:

for k, v in itertools.izip(config, x):

我得到了键 CONF_A、CONF_B 和 CONF_C。然而,这些值是相反的顺序,例如

{'CONF_A': c1, 'CONF_B': b1, 'CONF_C': 'a1'}

此外,我正在尝试弄清楚如何确保 C 的键与 CONF_C 值匹配,即

{'CONF_A': a1, 'CONF_B': b1, 'CONF_C1': 'c1'}
{'CONF_A': a1, 'CONF_B': b1, 'CONF_C2': 'c21'}

【问题讨论】:

    标签: python iteration enumeration itertools


    【解决方案1】:

    itertools.productitertools.chain 一起使用

    from itertools import product, chain
    
    list(product(config['CONF_A'], config['CONF_B'], chain.from_iterable(config['CONF_C'].values())))
    

    给我们

    [('a1', 'b1', 'c1'), ('a1', 'b1', 'c21'), ('a1', 'b1', 'c22'), ('a1', 'b2', 'c1'), 
     ('a1', 'b2', 'c21'), ('a1', 'b2', 'c22'), ('a2', 'b1', 'c1'), ('a2', 'b1', 'c21'), 
     ('a2', 'b1', 'c22'), ('a2', 'b2', 'c1'), ('a2', 'b2', 'c21'), ('a2', 'b2', 'c22'), 
     ('a3', 'b1', 'c1'), ('a3', 'b1', 'c21'), ('a3', 'b1', 'c22'), ('a3', 'b2', 'c1'), 
     ('a3', 'b2', 'c21'), ('a3', 'b2', 'c22')]
    

    编辑:

    a_gen = (('CONF_A', a) for a in config['CONF_A'])
    b_gen = (('CONF_B', b) for b in config['CONF_B'])
    c_gen = ((k, e) for k, v in config['CONF_C'].items() for e in v)
    for i in product(a_gen, b_gen, c_gen):
        print(i)
    

    给我们

    (('CONF_A', 'a1'), ('CONF_B', 'b1'), ('CONF_C1', 'c1'))
    (('CONF_A', 'a1'), ('CONF_B', 'b1'), ('CONF_C2', 'c21'))
    (('CONF_A', 'a1'), ('CONF_B', 'b1'), ('CONF_C2', 'c22'))
    (('CONF_A', 'a1'), ('CONF_B', 'b2'), ('CONF_C1', 'c1'))
    (('CONF_A', 'a1'), ('CONF_B', 'b2'), ('CONF_C2', 'c21'))
    (('CONF_A', 'a1'), ('CONF_B', 'b2'), ('CONF_C2', 'c22'))
    (('CONF_A', 'a2'), ('CONF_B', 'b1'), ('CONF_C1', 'c1'))
    (('CONF_A', 'a2'), ('CONF_B', 'b1'), ('CONF_C2', 'c21'))
    (('CONF_A', 'a2'), ('CONF_B', 'b1'), ('CONF_C2', 'c22'))
    (('CONF_A', 'a2'), ('CONF_B', 'b2'), ('CONF_C1', 'c1'))
    (('CONF_A', 'a2'), ('CONF_B', 'b2'), ('CONF_C2', 'c21'))
    (('CONF_A', 'a2'), ('CONF_B', 'b2'), ('CONF_C2', 'c22'))
    (('CONF_A', 'a3'), ('CONF_B', 'b1'), ('CONF_C1', 'c1'))
    (('CONF_A', 'a3'), ('CONF_B', 'b1'), ('CONF_C2', 'c21'))
    (('CONF_A', 'a3'), ('CONF_B', 'b1'), ('CONF_C2', 'c22'))
    (('CONF_A', 'a3'), ('CONF_B', 'b2'), ('CONF_C1', 'c1'))
    (('CONF_A', 'a3'), ('CONF_B', 'b2'), ('CONF_C2', 'c21'))
    (('CONF_A', 'a3'), ('CONF_B', 'b2'), ('CONF_C2', 'c22'))
    

    【讨论】:

    • 感谢您的回答。它适用于所有枚举,但我也希望重新获得密钥 - 请参阅 edit 了解详细信息。
    猜你喜欢
    • 2015-08-03
    • 2013-03-16
    • 1970-01-01
    • 2013-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-22
    • 1970-01-01
    相关资源
    最近更新 更多