【问题标题】:Is there a way to map a list of dicts according to the dict keys?有没有办法根据字典键映射字典列表?
【发布时间】:2021-06-03 20:47:08
【问题描述】:

我有一个看起来像的字典列表

[{'n': 3, 'topic': 4, 'shared_via_twitter': 'N'}, {'n': 72, 'topic': 1, 'shared_via_twitter': 'Y'}, {'n': 46, 'topic': 2, 'shared_via_twitter': 'N'}, {'n': 36, 'topic': 2, 'shared_via_twitter': 'Y'}, {'n': 5, 'topic': 4, 'shared_via_twitter': 'N'}, {'n': 29, 'topic': 2, 'shared_via_twitter': 'Y'}, {'n': 102, 'topic': 2, 'shared_via_twitter': 'Y'}, {'n': 13, 'topic': 8, 'shared_via_twitter': 'Y'}, {'n': 52, 'topic': 2, 'shared_via_twitter': 'N'}, {'n': 24, 'topic': 5, 'shared_via_twitter': 'N'}]

我希望能够将具有相同 topicshared_via_twitter 值的所有字典合并为一个,并更新新字典的 n 值以反映总和。

例如 如果我有

[{'n': 3, 'topic': 1, 'shared_via_twitter': 'N'}, {'n': 7, 'topic': 1, 'shared_via_twitter': 'N'}]

那么我想要{'n': 10, 'topic': 1, 'shared_via_twitter': 'N'} 作为结果。

我正在考虑使用类似的地图

def xs(x):
    # {'n': 3, 'topic': 4, 'shared_via_twitter': 'N'}
    # {'n': 7, 'topic': 4, 'shared_via_twitter': 'N'}
    if x['topic'] == v['topic'] and x['shared_via_twitter'] == v['shared_via_twitter']:
        x['n']+=v['n']
        v = dict(x)
        return x

g = map(xs, rows)

但这显然看起来不干净/工作。 任何想法将不胜感激。

【问题讨论】:

    标签: python python-3.x list python-2.7 dictionary


    【解决方案1】:

    这不是映射操作。目前尚不清楚您尝试在做什么,确切地说,因为 v 没有定义。但基本上,map 不是最好的工具,因为它对每个元素都应用了一个函数,你想按你的键分组并聚合 "n" 的值和求和。使用字典分组习语:

    >>> data = [{'n': 3, 'topic': 4, 'shared_via_twitter': 'N'}, {'n': 72, 'topic': 1, 'shared_via_twitter': 'Y'}, {'n': 46, 'topic': 2, 'shared_via_twitter': 'N'}, {'n': 36, 'topic': 2, 'shared_via_twitter': 'Y'}, {'n': 5, 'topic': 4, 'shared_via_twitter': 'N'}, {'n': 29, 'topic': 2, 'shared_via_twitter': 'Y'}, {'n': 102, 'topic': 2, 'shared_via_twitter': 'Y'}, {'n': 13, 'topic': 8, 'shared_via_twitter': 'Y'}, {'n': 52, 'topic': 2, 'shared_via_twitter': 'N'}, {'n': 24, 'topic': 5, 'shared_via_twitter': 'N'}]
    >>> grouper = {}
    >>> for d in data:
    ...     key = d['topic'], d['shared_via_twitter']
    ...     grouper[key] = grouper.get(key, 0) + d['n']
    ...
    >>> grouper
    {(4, 'N'): 8, (1, 'Y'): 72, (2, 'N'): 98, (2, 'Y'): 167, (8, 'Y'): 13, (5, 'N'): 24}
    

    您可以使用以下方法将其转换为最终形式:

    >>> [dict(topic=t, shared_via_twitter=s, n=n) for (t, s), n in grouper.items()]
    [{'topic': 4, 'shared_via_twitter': 'N', 'n': 8}, {'topic': 1, 'shared_via_twitter': 'Y', 'n': 72}, {'topic': 2, 'shared_via_twitter': 'N', 'n': 98}, {'topic': 2, 'shared_via_twitter': 'Y', 'n': 167}, {'topic': 8, 'shared_via_twitter': 'Y', 'n': 13}, {'topic': 5, 'shared_via_twitter': 'N', 'n': 24}]
    

    【讨论】:

      【解决方案2】:

      如果我正确理解您想要做什么,请尝试collections.defaultdictcollections.Counter

      import collections
      
      totals = collections.Counter()
      for d in data:
         totals[d['topic'], d['shared_via_twitter']] += d['n']
      

      这会将其保留在类似 {(1, 'N'): 10} 的结构中,您可以按原样使用它,也可以将其转换为 list-of-dicts 形式:

      converted = [
          {'n': n, 'topic': topic, 'shared_via_twitter': shared_via_twitter}
          for (topic, shared_via_twitter), n in totals.items()
      ]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-06-28
        • 2021-07-27
        • 1970-01-01
        • 1970-01-01
        • 2018-08-13
        • 2022-09-27
        • 1970-01-01
        • 2018-05-03
        相关资源
        最近更新 更多