考虑以下结构:
myObj1 = [{"id":1, "name":"john"},
{"id":2, "name":"roger"},
{"id":3, "name":"carlos"}]
myObj2 = [{"group": "myGroup1","persons":[1, 2, 3]},
{"group": "myGroup2", "persons":[2]},
{"group": "myGroup3", "persons":[1,3]}]
我希望产品具有以下结果:
result = [{"group": "myGroup1","persons":[{"id":1, "name":"john"},
{"id":2, "name":"roger"},
{"id":3, "name":"carlos"}]},
{"group": "myGroup2", "persons":[{"id":2, "name":"roger"}]},
{"group": "myGroup3", "persons":[{"id":1, "name":"john"},
{"id":3, "name":"carlos"}]}]
挑战在于"人员中的每一个价值。数组将其替换为id匹配的整个myObj1项值。
我可以使用类似3来实现这一点,但我想知道是否有使用插值,地图,过滤器,集等等的pythonic方式。我知道python这个词,但是从面试官那里得到了这个问题,他告诉我,我应该用1-2行代码来做这件事。
更新: 这是我的新手方法:
for item in myObj1:
id = item["id"]
for item2 in myObj2:
for i in range(len(item2["persons"])):
if item2["persons"][i] == id:
item2["persons"][i] = item
答案 0 :(得分:1)
以下内容如何:
result = [dict(x) for x in myObj2]
for grp in result:
grp["persons"] = [p for p in myObj1 if p["id"] in grp["persons"]]
我们创建一个新列表(使用dict(x) to ensure we don't retain references to the elements of
myObj2`),然后相应地更新。
答案 1 :(得分:1)
result = myObj2.copy()
for d in result:
d['persons'] = [[j for j in myObj1 if j['id']==i][0] for i in d['persons']]
result
输出:
[{'group': 'myGroup1',
'persons': [{'id': 1, 'name': 'john'},
{'id': 2, 'name': 'roger'},
{'id': 3, 'name': 'carlos'}]},
{'group': 'myGroup2', 'persons': [{'id': 2, 'name': 'roger'}]},
{'group': 'myGroup3',
'persons': [{'id': 1, 'name': 'john'}, {'id': 3, 'name': 'carlos'}]}]
答案 2 :(得分:1)
你可以试试这个:
myObj1 = [{"id":1, "name":"john"},
{"id":2, "name":"roger"},
{"id":3, "name":"carlos"}]
myObj2 = [{"group": "myGroup1","persons":[1, 2, 3]},
{"group": "myGroup2", "persons":[2]},
{"group": "myGroup3", "persons":[1,3]}]
final_dict = [{a:b if a != "persons" else c for a,b in d.items()} for c, d in zip(myObj1, myObj2)]
输出:
[{'persons': {'id': 1, 'name': 'john'}, 'group': 'myGroup1'}, {'persons': {'id': 2, 'name': 'roger'}, 'group': 'myGroup2'}, {'persons': {'id': 3, 'name': 'carlos'}, 'group': 'myGroup3'}]
答案 3 :(得分:0)
一种方法是替换"人员的价值观。关键,像这样:
[group.update({'persons':[myObj1[next(index for (index, d) in enumerate(myObj1) if d["id"] == idstud)] for idstud in group['persons'] if idstud in [i['id'] for i in myObj1]]}) for group in myObj2]
答案 4 :(得分:0)
您尝试执行的操作本质上是分组操作,然后映射字典值。这是itertools
模块真正发光的示例。
from itertools import chain, groupby
def concat(lists):
"""
Helper function to make concatenating lists/iterables easier
"""
return list(chain.from_iterable(lists))
by_group = {
id: list(people)
for id, people in groupby(myObj1, key=lambda person: person['id'])
}
result = [
{'group': group['group'],
'persons': concat(by_group[id] for id in group['persons'])}
for group in myObj2
]
在这个例子中,你仍然需要for循环,但现在很清楚那些循环正在尝试做什么。第一个是建立一个中间数据结构来跟踪谁拥有什么id。然后第二个是通过另一个数据结构并根据groupby
操作计算哪个组中的人。