[英]Iterate over two lists of dicts and create list of tuples without loop
我有兩個dicts列表: list1
和list2
。
print(list1)
[{'name': 'fooa', 'desc': 'bazv', 'city': 1, 'ID': 1},
{'name': 'bard', 'desc': 'besd', 'city': 2, 'ID': 1},
{'name': 'baer', 'desc': 'bees', 'city': 2, 'ID': 1},
{'name': 'aaaa', 'desc': 'bnbb', 'city': 1, 'ID': 2},
{'name': 'cgcc', 'desc': 'dgdd', 'city': 1, 'ID': 2}]
print(list2)
[{'name': 'foo', 'desc': 'baz', 'city': 1, 'ID': 1},
{'name': 'bar', 'desc': 'bes', 'city': 1, 'ID': 1},
{'name': 'bar', 'desc': 'bes', 'city': 2, 'ID': 1},
{'name': 'aaa', 'desc': 'bbb', 'city': 1, 'ID': 2},
{'name': 'ccc', 'desc': 'ddd', 'city': 1, 'ID': 2}]
我需要一個元組列表,它將包含兩個配對的dicts(每個列表中的一個dict),具有相同的city
和ID
。
我用雙循環做到了:
list_of_tuples = []
for i in list1:
for j in list2:
if i['ID'] == j['ID'] and i['city'] == j['city']:
list_of_tuples.append((i, j))
print(list_of_tuples)
[({'name': 'fooa', 'desc': 'bazv', 'city': 1, 'ID': 1},
{'name': 'foo', 'desc': 'baz', 'city': 1, 'ID': 1}),
({'name': 'fooa', 'desc': 'bazv', 'city': 1, 'ID': 1},
{'name': 'bar', 'desc': 'bes', 'city': 1, 'ID': 1}),
({'name': 'bard', 'desc': 'besd', 'city': 2, 'ID': 1},
{'name': 'bar', 'desc': 'bes', 'city': 2, 'ID': 1}),
({'name': 'baer', 'desc': 'bees', 'city': 2, 'ID': 1},
{'name': 'bar', 'desc': 'bes', 'city': 2, 'ID': 1}),
({'name': 'aaaa', 'desc': 'bnbb', 'city': 1, 'ID': 2},
{'name': 'aaa', 'desc': 'bbb', 'city': 1, 'ID': 2}),
({'name': 'aaaa', 'desc': 'bnbb', 'city': 1, 'ID': 2},
{'name': 'ccc', 'desc': 'ddd', 'city': 1, 'ID': 2}),
({'name': 'cgcc', 'desc': 'dgdd', 'city': 1, 'ID': 2},
{'name': 'aaa', 'desc': 'bbb', 'city': 1, 'ID': 2}),
({'name': 'cgcc', 'desc': 'dgdd', 'city': 1, 'ID': 2},
{'name': 'ccc', 'desc': 'ddd', 'city': 1, 'ID': 2})]
問題:如何以更加pythonic的方式(沒有循環)這樣做?
您可以使用itertools.product
和filter
:
from itertools import product
list1 = [{'name': 'fooa', 'desc': 'bazv', 'city': 1, 'ID': 1},
{'name': 'bard', 'desc': 'besd', 'city': 2, 'ID': 1},
{'name': 'baer', 'desc': 'bees', 'city': 2, 'ID': 1},
{'name': 'aaaa', 'desc': 'bnbb', 'city': 1, 'ID': 2},
{'name': 'cgcc', 'desc': 'dgdd', 'city': 1, 'ID': 2}]
list2 = [{'name': 'foo', 'desc': 'baz', 'city': 1, 'ID': 1},
{'name': 'bar', 'desc': 'bes', 'city': 1, 'ID': 1},
{'name': 'bar', 'desc': 'bes', 'city': 2, 'ID': 1},
{'name': 'aaa', 'desc': 'bbb', 'city': 1, 'ID': 2},
{'name': 'ccc', 'desc': 'ddd', 'city': 1, 'ID': 2}]
def condition(x):
return x[0]['ID'] == x[1]['ID'] and x[0]['city'] == x[1]['city']
list_of_tuples = list(filter(condition, product(list1, list2)))
這是一個非常適合pandas
的問題。 如果將列表轉換為DataFrame,則匹配ID
和city
上的記錄與兩個DataFrame的內部聯接相同 。
import pandas as pd
# convert lists to DataFrames
df1 = pd.DataFrame(list1)
df2 = pd.DataFrame(list2)
# merge the two DataFrames
print(df1.merge(df2, on=["ID", "city"]))
# ID city desc_x name_x desc_y name_y
#0 1 1 bazv fooa baz foo
#1 1 1 bazv fooa bes bar
#2 1 2 besd bard bes bar
#3 1 2 bees baer bes bar
#4 2 1 bnbb aaaa bbb aaa
#5 2 1 bnbb aaaa ddd ccc
#6 2 1 dgdd cgcc bbb aaa
#7 2 1 dgdd cgcc ddd ccc
現在,每行都有匹配的記錄。 由於desc
和name
列存在於兩者中(並且不用於合並),因此它們使用_x
和_y
進行下標以區分兩個源DataFrame。
您只需將其重新格式化為所需的輸出即可。 你可以使用to_dict
和列表理解來實現這個to_dict
:
list_of_tuples = [
(
{"name": r["name_x"], "desc": r["desc_x"], "city": r["city"], "ID": r["ID"]},
{"name": r["name_y"], "desc": r["desc_y"], "city": r["city"], "ID": r["ID"]}
) for r in df1.merge(df2, on=["ID", "city"]).to_dict(orient="records")
]
print(list_of_tuples)
#[({'ID': 1, 'city': 1, 'desc': 'bazv', 'name': 'fooa'},
# {'ID': 1, 'city': 1, 'desc': 'baz', 'name': 'foo'}),
# ({'ID': 1, 'city': 1, 'desc': 'bazv', 'name': 'fooa'},
# {'ID': 1, 'city': 1, 'desc': 'bes', 'name': 'bar'}),
# ({'ID': 1, 'city': 2, 'desc': 'besd', 'name': 'bard'},
# {'ID': 1, 'city': 2, 'desc': 'bes', 'name': 'bar'}),
# ({'ID': 1, 'city': 2, 'desc': 'bees', 'name': 'baer'},
# {'ID': 1, 'city': 2, 'desc': 'bes', 'name': 'bar'}),
# ({'ID': 2, 'city': 1, 'desc': 'bnbb', 'name': 'aaaa'},
# {'ID': 2, 'city': 1, 'desc': 'bbb', 'name': 'aaa'}),
# ({'ID': 2, 'city': 1, 'desc': 'bnbb', 'name': 'aaaa'},
# {'ID': 2, 'city': 1, 'desc': 'ddd', 'name': 'ccc'}),
# ({'ID': 2, 'city': 1, 'desc': 'dgdd', 'name': 'cgcc'},
# {'ID': 2, 'city': 1, 'desc': 'bbb', 'name': 'aaa'}),
# ({'ID': 2, 'city': 1, 'desc': 'dgdd', 'name': 'cgcc'},
# {'ID': 2, 'city': 1, 'desc': 'ddd', 'name': 'ccc'})]
嵌套循環不是“不是pythonic”。 但是,您可以使用列表推導實現相同的結果。 我不認為它更具可讀性:
[(i, j) for j in list2 for i in list1 if i['ID'] == j['ID'] and i['city'] == j['city']]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.