【问题标题】:Iterating over a list of dictionaries in python to find all occurances of a pair of values遍历python中的字典列表以查找所有出现的一对值
【发布时间】:2020-03-18 14:18:21
【问题描述】:

我搜索了一段时间,但找不到解决问题的确切方法。我有一个格式的字典列表:

d = [{"sender": "a", "time": 123, "receiver": "b", "amount": 2}, {"sender": "c", "time": 124, "receiver": "b", "amount": 10}, {"sender": "a", "time": 130, "receiver": "b", "amount": 5}]

我想找到迭代所有字典并计算给定的发送者-接收者对出现的次数以及总数的最佳方法。

所以我想得到:

result = [{"sender": "a", "receiver":b, "count": 2, "total_amount":7}, {"sender": "c", "receiver":b, "count": 1, "total_amount":10}]

我很确定我可以通过逐个迭代列表中的所有字典来完成这项工作,将信息保存在临时字典中,但这会导致大量嵌套 if 循环。我希望有一种更清洁的方法来做到这一点。

我知道我可以使用Counter 来计算唯一值的出现次数:

from collections import Counter
Counter(val["sender"] for val in d)

这会给我:

>>> ({"a":2, "c":1})

但我怎样才能为一对值执行此操作并为每个值分别设置字典?

提前谢谢你,我希望我的问题足够清楚

【问题讨论】:

    标签: python dictionary


    【解决方案1】:

    这是一种使用dict 方法的简单迭代的方法。

    例如:

    d = [{"sender": "a", "time": 123, "reciever": "b", "amount": 2}, {"sender": "c", "time": 124, "reciever": "b", "amount": 10}, {"sender": "a", "time": 130, "reciever": "b", "amount": 5}]
    result = {}
    for i in d:
        key = (i['sender'], i['reciever'])
        # del i['time']  # if you do not need `time` key
        if key not in result:
            i.update({'total_amount': i.pop('amount'), 'count': 1})
            result[key] = i
        else:
            result[key]['total_amount'] += i['amount']
            result[key]['count'] += 1
    
    print(list(result.values()))
    

    输出:

    [{'count': 2, 'reciever': 'b', 'sender': 'a', 'time': 123, 'total_amount': 7},
     {'count': 1, 'reciever': 'b', 'sender': 'c', 'time': 124, 'total_amount': 10}]
    

    【讨论】:

    • @Jan 由于多次键值修改,我没有使用它
    • 加一个来降低他的实际预期结果
    • 正如@ege 所说,这是我想要得到的结果,因为我希望之后能够将输出写入 json 文件,以便在网站上使用 javascript 显示。我会将此视为真正的答案,但 ege 的答案也非常有用
    【解决方案2】:

    纯python方式是创建一个sender:reciever对的新哈希表

    我更新了它以按要求计算total amount。

    d = [{"sender": "a", "time": 123, "reciever": "b", "amount": 2},
         {"sender": "c", "time": 124, "reciever": "b", "amount": 10},
         {"sender": "a", "time": 130, "reciever": "b", "amount": 5}]
    
    nd = {}
    
    for o in d:
      sender = o['sender']
      recv = o['reciever']
      amount = o['amount']
    
      k = sender + ":" + recv
      if k not in nd:
        nd[k] = (0, 0)
    
      nd[k] = (nd[k][0] + 1, nd[k][1] + amount)
    
    print nd
    

    导致{'c:b': (1, 10), 'a:b': (2, 7)}

    【讨论】:

    • 感谢您的回答。正如我在@Rakesh 的回答中提到的那样,一个最接近我想要的输出,因为我想将输出写入 json 并能够在网站上使用 javascript 显示它,所以我希望有一个包含所有键的字典.但是如果我需要在字典上再次执行此类操作,您的回答也非常有帮助。
    【解决方案3】:

    您可以使用 pandas 将字典列表解析为数据框。
    数据帧将允许您轻松总结某些发送方接收方对的 amount 字段。

    import pandas as pd
    
    dict = [{"sender": "a", "time": 123, "receiver": "b", "amount": 2},   
            {"sender": "c", "time": 124, "receiver": "b", "amount": 10},   
            {"sender": "a", "time": 130, "receiver": "b", "amount": 5}]
    
    df = pd.DataFrame.from_records(dict)
    group = df.groupby(by=['sender', 'receiver'])
    
    result = group.sum()
    result['occurrences'] = group.size()
    print(result)
    
    

    会输出

                     time  amount  occurrences
    sender receiver
    a      b          253       7            2
    c      b          124      10            1
    

    【讨论】:

    • 不错的答案,但它不计算发送者接收者对出现的次数?
    • This answer 同时帮助两者
    • 现在包括出现次数,尽管此时我会选择纯 python 方法。
    【解决方案4】:

    Max Crous's 答案比这更优雅,但如果你想避免额外的库:这是一种纯 python 方式:

    import collections
    result = collections.defaultdict(lambda : [0,0])
    for e in d: 
        result[(e['sender'],e['reciever'])][0]+=e['amount']
        result[(e['sender'],e['reciever'])][1]+=1 
    

    Result 现在是一个字典,其中发送者和接收者的元组作为键,2 元素列表 [total_amount, count] 作为值

    【讨论】:

      【解决方案5】:

      Imo 最简单和最干净的解决方案是使用 defaultdict:

      from collections import defaultdict
      
      dct = [{"sender": "a", "time": 123, "reciever": "b", "amount": 2},
             {"sender": "c", "time": 124, "reciever": "b", "amount": 10},
             {"sender": "a", "time": 130, "reciever": "b", "amount": 5}]
      
      result = defaultdict(int)
      for item in dct:
          key = "{}:{}".format(item["sender"], item["reciever"])
          result[key] += item["amount"]
      
      print(result)
      

      结果

      defaultdict(<class 'int'>, {'a:b': 7, 'c:b': 10})
      

      此外,不要调用你的变量dict 或list。

      【讨论】:

        【解决方案6】:

        使用字典,您可以将发送者设置为键,将值设置为接收者和数量,然后递增/添加接收者,数量

        dict = [{"sender": "a", "time": 123, "reciever": "b", "amount": 2}, {"sender": "c", "time": 124, "reciever": "b", "amount": 10}, {"sender": "a", "time": 130, "reciever": "b", "amount": 5}]
        dict1={}
        for eachitem in dict:
                if(eachitem["sender"] in dict1.keys()):
                     dict1[eachitem["sender"]]["amount"]=dict1[eachitem["sender"]]["amount"]+eachitem["amount"]
                     dict1[eachitem["sender"]]["reciever"]+=1
        
                else:
                    dict1[eachitem["sender"]]={"reciever":1,"amount":eachitem["amount"]}
        
        print(dict1)
        

        输出

        {'a': {'reciever': 2, 'amount': 7}, 'c': {'reciever': 1, 'amount': 10}}
        

        【讨论】:

          猜你喜欢
          • 2019-01-11
          • 1970-01-01
          • 2013-08-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多