2017-10-06 61 views
2

從兩個不同的名單列表考慮以下結構:生成的關鍵

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方式。我知道的蟒蛇單詞,但從這個問題得到一個採訪者,他告訴我,我應該用1-2行代碼來做到這一點。

UPDATE: 這裏是什麼是我的新手的做法:

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 

回答

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'}]}] 
+0

感謝您的回答,看來我的主要缺少的一點是,與「in」我可以直接在第二個字典中找到值,從等式中刪除1。我認爲所有的解決方案都對我有幫助,爲了簡單起見,我將其標記爲正確的 –

+0

@FilipeAlcântara - 歡迎您! – Transhuman

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`),然後相應地更新。

+0

或者你可以做'x.copy()' –

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] 
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操作計算誰在哪個組中。

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'}]