【问题标题】:Dictionary comprehension with nested list, prevent overwrite带有嵌套列表的字典理解,防止覆盖
【发布时间】:2015-06-11 10:48:54
【问题描述】:

我正在尝试使用嵌套列表来使用字典理解。只要键是唯一的,一切正常。但是,如果存在多个键,我想将值附加到该键而不是覆盖该值。这可以使用理解吗?

seq1 = [[1, [1,2,3,4]], [2, [5,6,7]]]
seq2 = [[1, [1,2,3,4]], [1, [5,6,7]]]

print {key: [val] for key, val in seq1}  # Or dict(seq1)
>>> {1: [[1, 2, 3, 4]], 2: [[5, 6, 7]]}

print {key: [val] for key, val in seq2}
>>> {1: [[5, 6, 7]]}  # First value is overwritten

# Desired output:
def index_reads(reads):
    result = {}
    for i in reads:
        d = dict([i])
        for key, val in d.iteritems():
            if key in result:
                result[key].append(val)
            else:
                result[key] = [val]
    return result

print index_reads(seq1)
>>> {1: [[1, 2, 3, 4]], 2: [[5, 6, 7]]}

print index_reads(seq2)
>>> {1: [[1, 2, 3, 4], [5, 6, 7]]}

抱歉,我找不到这个问题的重复。

【问题讨论】:

    标签: python list dictionary


    【解决方案1】:

    您不需要列表理解。作为一种更 Pythonic 的方式,您可以使用 dict.setdefault() 方法:

    >>> d={key: [val] for key, val in seq1}
    >>> for key, val in seq2:
    ...   d.setdefault(key,[]).append(val)
    ... 
    >>> d
    {1: [[1, 2, 3, 4], [1, 2, 3, 4], [5, 6, 7]], 2: [[5, 6, 7]]}
    

    您也可以将collections.defaultdict 用于此类任务。

    当您在seq2 中有不同的键时,它也会显示出它的力量,例如:

    >>> seq2 = [[1, [1,2,3,4]], [5, [5,6,7]]]
    >>> d={key: [val] for key, val in seq1}
    >>> for key, val in seq2:
    ...   d.setdefault(key,[]).append(val)
    ... 
    >>> d
    {1: [[1, 2, 3, 4], [1, 2, 3, 4]], 2: [[5, 6, 7]], 5: [[5, 6, 7]]}
    

    如果您不想保留重复项,可以使用 defaultdictset 作为容器:

    >>> from collections import defaultdict
    >>> seq1 = [[1, [1,2,3,4]], [2, [5,6,7]]]
    >>> seq2 = [[1, [1,2,3,4]], [1, [5,6,7]]]
    >>> 
    >>> d=defaultdict(set)
    >>> for key, val in seq1+seq2:
    ...   d[key].add(tuple(val))
    ... 
    >>> d
    defaultdict(<type 'set'>, {1: set([(5, 6, 7), (1, 2, 3, 4)]), 2: set([(5, 6, 7)])})
    

    【讨论】:

    • 或使用defaultdict
    • @KarolyHorvath 是的,确实 ;)
    • 谢谢 我去看看,但输出与预期略有不同。我现在要编辑,抱歉。
    • @kezzos 那么你期待什么?
    • 我想单独处理列表,如果示例中不存在 seq1。如果我 d={key: [val] for key, val in seq2} 值被覆盖
    【解决方案2】:

    您可以使用groupby 中的itertools

    import itertools
    import operator
    
    seq1 = [[1, [1,2,3,4]], [2, [5,6,7]]]
    seq2 = [[1, [1,2,3,4]], [1, [5,6,7]]]
    
    def index_reads(seq):
        return {k: [i[1] for i in g] for k, g in itertools.groupby(seq, operator.itemgetter(0))}
    
    print index_reads(seq1)
    print index_reads(seq2)
    

    输出

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

    【讨论】:

      【解决方案3】:

      是的,使用 defaultdict 也可以:

      from collections import defaultdict
      
      seq1 = [[1, [1,2,3,4]], [2, [5,6,7]]]
      seq2 = [[1, [1,2,3,4]], [1, [5,6,7]]]
      
      d={key: [val] for key, val in seq1}
      d = defaultdict(list)
      for key, val in seq2:
          d[key].append(val)
      
      print d
      

      然后:

      [(1, [[1, 2, 3, 4], [5, 6, 7]])
      

      或者如果我们删除 seq1,

      seq2 = [[1, [1,2,3,4]], [1, [5,6,7]]]
      d={key: [val] for key, val in seq2}
      d = defaultdict(list)
      for key, val in seq2:
          d[key].append(val)
      print d
      

      你将再次拥有:

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

      【讨论】:

        猜你喜欢
        • 2021-12-22
        • 2017-12-25
        • 1970-01-01
        • 1970-01-01
        • 2015-04-11
        • 2021-02-23
        • 2017-03-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多