【问题标题】:Merge values of same key, in list of dicts在字典列表中合并相同键的值
【发布时间】:2015-08-25 17:50:42
【问题描述】:

我对 python 2.7 比较陌生,尽管在 StackOverflow 上进行了广泛搜索,但无法弄清楚以下内容:

我有一个 listdicts 我不想组合,当键相同时,并添加特定值(在示例中为 'price')。

输入:

[{'id1': 'a', 'price': '2', 'color': 'green'}, {'id1': 'b', 'price': '5', 'color': 'red'}, {'id1': 'a', 'price': '2', 'color': 'green'}] 

预期:

[{'id1': 'a', 'price': '4', 'color': 'green'}, {'id1': 'b', 'price': '5', 'color': 'red'}]

【问题讨论】:

    标签: python list python-2.7 dictionary


    【解决方案1】:

    与编辑前的问题相同。

    >>> data = [{'id1': 'a', 'price': '2', 'color': 'green'},
    ...         {'id1': 'b', 'price': '5', 'color': 'red'},
    ...         {'id1': 'a', 'price': '2', 'color': 'green'}]
    

    构造一个临时字典并在其中累积值

    >>> temp = {}
    >>> for d in data:
    ...     if d['id1'] not in temp:
    ...         temp[d['id1']] = {}
    ...     temp_d = temp[d['id1']]
    ...     temp_d['price'] = temp_d.get('price', 0) + int(d['price'])
    ...     temp_d.setdefault('colors', set()).add(d['color'])
    ... 
    >>> temp
    {'a': {'colors': {'green'}, 'price': 4}, 'b': {'colors': {'red'}, 'price': 5}}
    

    然后使用列表推导和字典推导,重构字典列表。

    >>> [{'id1': k, 'price': v['price'], 'colors': v['colors']} for k, v in temp.items()]
    [{'id1': 'a', 'colors': {'green'}, 'price': 4}, {'id1': 'b', 'colors': {'red'}, 'price': 5}]
    

    >>> data = [{'id1': 'a', 'price': '2'}, {'id1': 'b', 'price': '5'},
    ...         {'id1': 'a', 'price': '2'}]
    

    创建一个临时字典,我们可以在其中累积价格总和与其 ID,

    >>> temp = {}
    >>> for d in data:
    ...     temp[d['id1']] = temp.get(d['id1'], 0) + int(d['price'])
    ... 
    >>> temp
    {'a': 4, 'b': 5}
    

    这里我们尝试从temp获取d['id1']的值,如果没有找到,则返回0。然后,我们从当前字典中添加 price,并将结果存储回 temp 中,并针对当前的 id1。

    然后重构字典列表,使用list comprehension 和字典理解,像这样

    >>> [{'id1': k, 'price': temp[k]} for k in temp]
    [{'price': 4, 'id1': 'a'}, {'price': 5, 'id1': 'b'}]
    

    【讨论】:

    • 非常好。唯一的问题是第一个字典实际上有另一个值,颜色,在其中一次出现 {'id1': 'a', 'price': '2', 'color': 'red'} 我如何保持这个最后的命令?
    • @DauleDK 对于所有字典中给定的id1,颜色是否相同?例如,如果id1a,那么颜色是否总是green
    • 并非总是如此,也许可以将这些值连接起来?
    • @DauleDK 嗯,那你可以把它做成一组颜色,对吧?请记住:集合不会保留重复值。
    • 如果值永远不会改变,答案会是什么样子(我想这更简单?)
    【解决方案2】:

    这不如@thefourtheye 好,但似乎对我有用:

    di = [{'id1': 'a', 'price': '2', 'color': 'green'}, {'id1': 'b', 'price': '5', 'color': 'red'}, {'id1': 'a', 'price': '2', 'color': 'green'}] 
    
    # Make a dict to hold new values!
    newvals = {}
    
    for d in di:
        for key, value in d.iteritems():
            if value.isdigit():
                if value in newvals:
                    newvals[value] += int(value)
                else:
                    newvals[value] = int(value)
            else:
                if value not in newvals:
                    newvals[value] = value
    
    for d in di:
        for nkey, nvalue in d.iteritems():
            d[nkey] = newvals[nvalue]
    
    # Make a unique list of dicts
    print {v['id1']:v for v in di}.values()
    
    >>>[{'color': 'green', 'price': 4, 'id1': 'a'}, {'color': 'red', 'price': 5, 'id1': 'b'}]
    

    【讨论】:

      【解决方案3】:

      这对我有用:

      import collections 
      from functools import reduce
      
      data = [{'id1': 'a', 'price': '2', 'color': 'green'},
              {'id1': 'b', 'price': '5', 'color': 'red'},
              {'id1': 'a', 'price': '2', 'color': 'green'},
              {'id1': 'c', 'price': '2', 'color': 'blue'},
              {'id1': 'b', 'price': '5', 'color': 'red'},
              {'id1': 'b', 'price': '5', 'color': 'red'},
              {'id1': 'd', 'price': '1', 'color': 'white'},
              {'id1': 'b', 'price': '10', 'color': 'red'},
              {'id1': 'd', 'price': '20', 'color': 'yellow'}
              ]
      
      valores = [list(item.values()) for item in data]
      valores=[[item[0],int(item[1]),item[2]] for item in valores]
      
      dicc = collections.defaultdict(list)
      for item in valores:
          dicc[item[0]].append(item[1])
      res=list(dicc.items())
      res_def=[(t[0],sum(t[1])) for t in res]
      
      colors=[dicc['color'] for dicc in data for item in res_def if item[0] == dicc['id1'] ]          
      colors_unicos=reduce(lambda l, x: l.append(x) or l if x not in l else l, colors, [])
      for lista in res_def:
          lista.append(colors_unicos.pop(0))
      
      data_resultado=[{'id1':lista[0],'price':lista[1],'color':lista[2]}for lista in res_def]
      

      输出是: [{'id1': 'a', 'price': 4, 'color': 'green'}, {'id1': 'b', 'price': 25, 'color': 'red'}, { 'id1': 'c', 'price': 2, 'color': 'blue'}, {'id1': 'd', 'price': 1, 'color': 'white'}, {'id1 ':'e','价格':20,'颜色':'黄色'}]

      【讨论】:

        【解决方案4】:

        我已经设法像这样压缩代码:

        import itertools as it
        from operator import itemgetter
        
        grupos = it.groupby(sorted(data, key=itemgetter('id1')), key=itemgetter('id1'))
        res = [{'id1': v, 'price': sum(int(dicc['price']) for dicc in diccs) } for v, diccs in 
        grupos]
        print(res)
        

        输出是:

        [{'id1': 'a', 'price': 4}, {'id1': 'b', 'price': 25}, {'id1': 'c', 'price': 2}, {'id1': 'd', 'price': 1}, {'id1': 'e', 'price': 20}]
        

        【讨论】:

          猜你喜欢
          • 2018-01-20
          • 2019-11-19
          • 2017-12-02
          • 2022-12-03
          • 2022-12-18
          • 1970-01-01
          • 2020-03-12
          • 2020-10-14
          • 2017-04-20
          相关资源
          最近更新 更多