映射嵌套在字典中的列表

Mapping over a list nested inside a dict

数据

我很好奇我是否可以转换以下数据

old_data = {
  "key0": [obj0, obj1],
  "key1": [obj2, obj3]
}

data = {
  "key0": [obj0.id, obj1.id],
  "key1": [obj2.id, obj3.id]
}

使用听写理解。

所以基本上只是用对象本身的单个属性替换那些列表对象。所有对象都来自同一类型,因此肯定具有 id 属性。

听写理解

我提出了以下无效的解决方案:

data = {
  key: [obj.id]
  for key, obj_list in old_data.items()
  for obj in obj_list
}

问题

由于这一行,生成的字典仅包含具有一个值(迭代的最后一个值)的列表:

key: [obj.id]

每次只创建一个具有一个值的新列表。

所以我没有创建新列表,而是想 appendobj_id 到现有列表,但我不知道如何。 我认为它一定看起来像这样:

key: data[key].append(obj.id)

但显然这也行不通,因为 data 尚未分配,即使它会:第一个 obj.id 无法附加,因为列表从未初始化。

(我正在使用 Python 3.7)

列表理解

所以我找到了一个使用列表理解的解决方案:

data = {
  key: [obj.id for obj in obj_list]
  for key, obj_list in old_data.items()      
}

只需将循环 (for obj in obj_list) 移动到列表理解中。

这也解决了第一个 obj 不存在列表以及其他 obj 不需要 append 方法或类似方法的问题。

函数方法

这里有一个不是很 pythonic,但仍然很有趣的方法:

from functools import partial
from operator import attrgetter

old_data = {
  "key0": [obj0, obj1],
  "key1": [obj2, obj3]
}

data = dict(zip(old_data, map(list, map(partial(map, attrgetter('id')), old_data.values()))))