【问题标题】:Is there any simple way to swap python dictionary key values where values are list有没有简单的方法来交换值是列表的python字典键值
【发布时间】:2017-10-06 20:34:23
【问题描述】:

是否有任何简单的方法来交换 python 字典键值,其中值是列表 我的字典就像跟随

d={1:[1,2,3,4],2:[2,3,4],5:[1,3,6,7]}

我想从它生成一个字典,如下所示

a={1:[1,5],2:[1,2],3:[1,2,5],4:[1,2],6:[5],7:[5]}

我用反向测试过

dict(map(reversed, d.items())

它不会使用列表中的项目迭代和创建键返回 TypeError: unhashable type: 'list'

我正在寻找任何可用于实现此目的的内联方法

【问题讨论】:

  • 听起来你想要一个有向图。
  • 你关心列表元素的顺序吗?
  • 不关心订单

标签: python dictionary


【解决方案1】:

这将起作用:

def revdict(d):
    r = {}
    for k in d:
        for v in d[k]:
            if v not in r:
                r[v] = [k]
            else:
                r[v].append(k)
    return r

那么你可以这样做:

d={1:[1,2,3,4],2:[2,3,4],5:[1,3,6,7]}
a = revdict(d)
print(a)

如果您想避免检查新密钥,可以使用defaultdict,然后始终追加。

【讨论】:

    【解决方案2】:

    你的方法行不通,因为你的目标是构建一个字典:

    <s>{[1,2,3,4]: 1, [2,3,4]: 2, [1,3,6,7]: 5}</s>

    但由于列表是不可散列的,因此它们不能用作键(而且它也不是您打算构建的)。

    你最好使用defaultdict

    from collections import defaultdict
    
    result = defaultdict(list)
    for k, vs in d.items():
        for v in vs:
            result[v].append(k)
    

    在此操作之后,result 是一个 defaultdictvanilla dict 的子类),它将值列表中的项目映射到键(包含该值)。喜欢:

    >>> result
    defaultdict(<class 'list'>, {1: [1, 5], 2: [1, 2], 3: [1, 2, 5], 4: [1, 2], 6: [5], 7: [5]})
    

    您可以选择使用:

    result = dict(result)
    

    用这些值创建一个新字典(从而删除defaultdict)。

    请注意:

    • 由于大多数 Python 解释器不会对字典进行排序(这绝对不是您可以做出的硬性假设),因此列表中元素的顺序可能会有所不同;和
    • 您的字典d 中列表中的项目应该是可散列的

    【讨论】:

      【解决方案3】:

      这真的不适合单线;你把需要做的事情称为简单的逆转,过于简单化了。

      真正的反转只是将值映射到键而不是键到值,您可以这样做(将列表稍微但必要地更改为元组):

      >>> print dict((tuple(d[k]), k) for k in d)
      {(1, 3, 6, 7): 5, (2, 3, 4): 2, (1, 2, 3, 4): 1}
      

      你想要的要复杂得多,通常被称为字典的转置。

      from operator import itemgetter as ig
      from itertools import groupby
      
      transposed_dict = dict((k, map(ig(1), v)) 
                             for k, v in groupby(
                                            sorted((nk, k) for k in d for nk in d[k]),
                                                   key=ig(0)))
      

      这并没有什么特别简单的,虽然从概念上来说还不错:

      1. (nk, k) for k in d for nk in d[k] 从字典中创建一个扩展的关联列表,键和值倒置。

      2. groupby 收集所有具有共同第一个元素的元组

      3. (k, map(ig(1), v)) 将具有共同第一个元素的元组收集到一个元组中:(1,1), (1,2) =&gt; (1, [1,2])

      4. 步骤 3 中的元组用于构建新字典。

      不过,使用简单的 3 行 for 循环会好得多,如 Willem Van Onsem 所示;该循环的本质在于sorted 使用的生成器表达式;其他一切都只是处理避免可变变量的尝试。并非所有内容都应该(或可以)简化为简单的单行。

      【讨论】:

        猜你喜欢
        • 2019-06-24
        • 1970-01-01
        • 1970-01-01
        • 2015-10-18
        • 2010-11-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多