转换字典列表,根据键组合列表项

时间:2019-11-01 13:37:18

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

给出字典列表,例如:

history = [
  {
    "actions": [{"action": "baz", "people": ["a"]}, {"action": "qux", "people": ["d", "e"]}],
    "events": ["foo"]
  },
  {
    "actions": [{"action": "baz", "people": ["a", "b", "c"]}],
    "events": ["foo", "bar"]
  },
]

获取字典列表的最有效方法(虽然仍然可读)是什么,其中每个字典是唯一的event,并且基于{{1} }键。例如,对于上面的列表,所需的输出是:

action

我无法更改输出结构,因为它已被外部设备消耗。我编写了下面的代码,该代码可以工作,但是非常冗长且可读性很差。

output = [
    {
      "event": "foo", 
      "actions": [
        {"action": "baz", "people": ["a", "b", "c"]}, 
        {"action": "qux", "people": ["d", "e"]}
      ]
    },
    {
      "event": "bar", 
      "actions": [
        {"action": "baz", "people": ["a", "b", "c"]}
      ]
    },
]

我只针对python3.6 +

2 个答案:

答案 0 :(得分:2)

您可以将collections.defaultdictitertools.groupby一起使用:

from collections import defaultdict
from itertools import groupby as gb
d = defaultdict(list)
for i in history:
  for b in i['events']:
    d[b].extend(i['actions'])

new_d = {a:[(j, list(k)) for j, k in gb(sorted(b, key=lambda x:x['action']), key=lambda x:x['action'])] for a, b in d.items()}
result = [{'event':a, 'actions':[{'action':c, 'people':list(set([i for k in b for i in k['people']]))} for c, b in d]} for a, d in new_d.items()]

输出:

[
 {'event': 'foo', 
  'actions': [
     {'action': 'baz', 'people': ['b', 'a', 'c']}, 
     {'action': 'qux', 'people': ['d', 'e']}
    ]
  }, 
 {'event': 'bar', 
   'actions': [{'action': 'baz', 'people': ['b', 'a', 'c']}]
  }
 ]

答案 1 :(得分:0)

答案不是那么冗长,但可读性更好。此外,它不依赖于其他任何东西,而只是标准的python。

tmp_dict = {}
for d in history:
    for event in d["events"]:
        if event not in tmp_dict:
            tmp_dict[event] = {}
            for actions in d["actions"]:
                tmp_dict[event][actions["action"]] = actions["people"]
        else:
            for actions in d["actions"]:
                if actions["action"] in tmp_dict[event]:
                    tmp_dict[event][actions["action"]].extend(actions["people"])
                else:
                    tmp_dict[event][actions["action"]] = actions["people"]

output = [{"event": event, "actions": [{"action": ac, "people": list(set(peop))} for ac, peop in tmp_dict[event].items()]} for event in tmp_dict]

print (output)

输出:

[
   {'event': 'foo',
    'actions': [
                {'action': 'qux', 'people': ['e', 'd']},
                {'action': 'baz', 'people': ['a', 'c', 'b']}
               ]
   },
   {'event': 'bar',
    'actions': [{'action': 'baz', 'people': ['a', 'c', 'b']}]
   }
]