簡體   English   中英

迭代兩個dicts列表並創建沒有循環的元組列表

[英]Iterate over two lists of dicts and create list of tuples without loop

我有兩個dicts列表: list1list2

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),具有相同的cityID

我用雙循環做到了:

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.productfilter

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,則匹配IDcity上的記錄與兩個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

現在,每行都有匹配的記錄。 由於descname列存在於兩者中(並且不用於合並),因此它們使用_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM