【问题标题】:Less code on multi key dictionary initialization多键字典初始化的代码更少
【发布时间】:2014-01-16 16:14:31
【问题描述】:

我有这样的代码(Python 2.7+):

target = "some_string_key1_key3_key5_key6"

some_dict = {
    'key1': 'value1',
    'key2': 'value1',
    'key3': 'value2',
    'key4': 'value2',
    'key5': 'value3',
    'kyy6': 'value4',
}

for k, v in some_dict.iteritems():
    target = target.replace(k, v)

如您所见,有不同的键使用相同的值(key1 和 key2 / key3 和 key4)。在我的例子中,所有的键和值都是字符串。

有没有可能在字典初始化上减少代码并仍然得到

for k, v in some_dict.iteritems()

仅使用标准 python 2.7 模块的行为没有改变?

我试过multi_key_dict,但对我来说不太方便,因为语法略有不同。

我想要达到的就是这样的:

new_cool_dict = {
    ['key1', 'key2', ]: 'value1',
    ['key3', 'key4', ]: 'value2',
    'key5': 'value3',
    'key6': 'value6',
}

for k, v in new_cool_dict.iteritems():
    target = target.replace(k, v)

【问题讨论】:

  • “new_cool_dict”方法的一个问题是listtuple 不能互换使用。由于tuple 是可散列的,因此它可以用作dict 键。 list 实例不能。您可以编写自己的类,专门检查预期的键是否既是可迭代的又是 list 的实例,然后继续为 list 中的每个键插入键值对。
  • 但是当传递tuple 时它不能以相同的方式工作,并且当键是str 时可能还需要特殊处理。最后,尝试避免使用纯语法可能会增加更多的代码和开销,而不是在实际 dict 实例化时节省的最终微小的语法增益。
  • 另一个问题是您问题顶部的dict 实例化(您不喜欢的“长”示例)可以很好地作为驻留在配置文件中的纯 Python 文字,并且几乎可以直接翻译为 Yaml 或其他序列化方法。你所做的任何改变都会以一种可能比只是稍微冗长的实例化更糟糕的方式来掩盖它。

标签: python python-2.7 dictionary


【解决方案1】:

我发现这较少有用且易读,但您可以在一行中使用多个分配:

some_dict = {
    'key5': 'value3',
    'kyy6': 'value4',
}
some_dict['key1'] = some_dict['key2'] = 'value1'
some_dict['key3'] = some_dict['key4'] = 'value2'

另一种方法是构建一个扩展元组键的工厂函数:

def expand_tuple_keys(d):
    result = {}
    for key, value in d.iteritems():
        if not hasattr(key, '__iter__'):
            key = (key,)
        result.update((k, value) for k in key)
    return result

然后使用:

new_cool_dict = expand_tuple_keys({
    ('key1', 'key2'): 'value1',
    ('key3', 'key4'): 'value2',
    'key5': 'value3',
    'key6': 'value6',
})

演示:

>>> def expand_tuple_keys(d):
...     result = {}
...     for key, value in d.iteritems():
...         if not hasattr(key, '__iter__'):
...             key = (key,)
...         result.update((k, value) for k in key)
...     return result
... 
>>> expand_tuple_keys({
...     ('key1', 'key2'): 'value1',
...     ('key3', 'key4'): 'value2',
...     'key5': 'value3',
...     'key6': 'value6',
... })
{'key3': 'value2', 'key2': 'value1', 'key1': 'value1', 'key6': 'value6', 'key5': 'value3', 'key4': 'value2'}

【讨论】:

  • 这至少可以说更易于维护/干燥,因为您不重复字符串文字。
  • 如果您希望键既是单个值又是 tuples,这很糟糕。例如,如果我真的想要 {'a':1, ('b', 'c'):2}tuple ('b', 'c') 作为键之一,但随后想为两个不同的键添加重复值,'d''e'。最好让它只作为“expand_list_keys”工作,因为list 不可散列,因此不能被误认为是可能的密钥。
  • @EMS:您不能使用 list 对象作为键。您始终可以使用 (('a', 'b'),) 单项元组,并将元组作为唯一值。
  • @EMS:注意我现在传入一个字典;您必须改为切换到元组列表,这会变得冗长乏味。
  • 不,我是说你不应该在expand_tuple_keys 中使用字典本身。如果不清楚,我深表歉意——我认为您不理解我的建议。我是说,不要从任何将元组作为键然后被修改的东西开始。相反,传递lists(在这种情况下不要使用{} 符号),这样就不会与dict 处理tuple 键的本机方式混淆。
【解决方案2】:

为方便起见,您也可以反过来定义字典:

my_dict = {
    'value1': ['key1', 'key2'],
    'value2': ['key3', 'key4'],
    'value3': ['key5']
}

然后将其转换为更有用的表示:

>>> dict((k, v) for (v, l) in my_dict.iteritems() for k in l)
{'key1': 'value1',
 'key2': 'value1',
 'key3': 'value2',
 'key4': 'value2',
 'key5': 'value3'}

【讨论】:

    【解决方案3】:

    我建议将键设置为元组并稍微更改您的 for 循环,像这样

    target = "some_string_key1_key3_key5_key6"
    
    some_dict = {
        ('key1', 'key2'): 'value1',
        ('key3', 'key4'): 'value2',
        ('key5',): 'value3',
        ('key6',): 'value6',
    }
    
    for k, v in some_dict.iteritems():
        target = reduce(lambda x, y: x.replace(y, v), k, target)
    
    print target
    

    输出

    some_string_value1_value2_value3_value6
    

    【讨论】:

    • 哇,这几乎就是我想要的 :) 谢谢!
    • @АндрейБаюн 酷 :) 如果对您有帮助,请考虑 accepting this answer :)
    【解决方案4】:

    反转键和值 ;-)

    dict = { 
       'value1': ['key1', 'key2'],
       'value2': ['key3', 'key3'],
       'value3': ['key5'],
       'value4': ['key6']
    
    }
    
    
    
    for v, ks in dict.iteritems:
       for k in ks:
           target = target.replace.(k, v)
    

    Bob 是你的叔叔(尽管我可能会将 k 重命名为 v,反之亦然

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-14
      • 1970-01-01
      • 2017-10-23
      • 2015-04-15
      • 1970-01-01
      • 2011-12-19
      相关资源
      最近更新 更多