[英]Finding difference between two list of dictionary in Python
我試圖找到2個字典列表之間的區別。 我在這個論壇中找到了一些信息,但沒有達到我的目的。
incoming_rows = [{'column_name': 'LOAD_ID', 'data_type': 'int', 'table_name': 'CONFIG'},
{'column_name': 'ROW_NUMBER', 'data_type': 'int', 'table_name': 'CONFIG'},
{'column_name': 'CREATE_DATE', 'data_type': 'VARCHAR(20)', 'table_name': 'CONFIG'},
{'column_name': 'CONFIG_TYPE', 'data_type': 'varchar(1)', 'table_name': 'CONFIG'},
{'column_name': 'CONFIG_ID', 'data_type': 'numeric(10,0)', 'table_name': 'CONFIG'}
]
available_row = [{'column_name': 'LOAD_ID', 'data_type': 'int', 'table_name': 'CONFIG'},
{'column_name': 'ROW_NUMBER', 'data_type': 'int', 'table_name': 'CONFIG'},
{'column_name': 'CREATE_DATE', 'data_type': 'date', 'table_name': 'CONFIG'}
]
在這里,我需要將incoming_rows與available_row字典列表進行比較,差異想要列在另一個dict格式列表中。這里我的表名是唯一的。 條件:1。任何新添加的列。 2.數據類型的任何更改如果這兩個條件為真,則expected_row應僅包含這些已更改的行。
# expected output
expected_row=[{'column_name': 'CONFIG_TYPE', 'data_type': 'varchar(1)', 'table_name': 'CONFIG'},
{'column_name': 'CONFIG_ID', 'data_type': 'numeric(10,0)', 'table_name': 'CONFIG'},
{'column_name': 'CREATE_DATE', 'data_type': 'VARCHAR(20)', 'table_name': 'CONFIG'}
]
套裝是解決這個問題的完美方案。 不幸的是,python不允許你將字典添加到集合中,因為它們是可變的,並且它們的哈希碼可能在插入和查找之間發生變化。
如果你“凍結”項目使它們不可變,你可以將它們添加到設置對象而不是列表; 然后使用減號運算符取一組差異:
In [20]: i_set = { frozenset(row.items()) for row in incoming_rows }
In [21]: a_set = { frozenset(row.items()) for row in available_row }
In [22]: (i_set - a_set)
Out[22]:
{frozenset({('column_name', 'CONFIG_ID'),
('data_type', 'numeric(10,0)'),
('table_name', 'CONFIG')}),
frozenset({('column_name', 'CREATE_DATE'),
('data_type', 'VARCHAR(20)'),
('table_name', 'CONFIG')}),
frozenset({('column_name', 'CONFIG_TYPE'),
('data_type', 'varchar(1)'),
('table_name', 'CONFIG')})}
編輯:取消凍結:
In [25]: [dict(i) for i in i_set - a_set]
Out[25]:
[{'column_name': 'CONFIG_ID',
'data_type': 'numeric(10,0)',
'table_name': 'CONFIG'},
{'column_name': 'CREATE_DATE',
'data_type': 'VARCHAR(20)',
'table_name': 'CONFIG'},
{'column_name': 'CONFIG_TYPE',
'data_type': 'varchar(1)',
'table_name': 'CONFIG'}]
對於大型數據集,尤其是在處理數字數據時,您可能會發現第三方庫的性能更高。 例如,Pandas直接接受目錄列表:
import pandas as pd
# convert lists of dictionaries to dataframes
df_incoming, df_available = map(pd.DataFrame, (incoming_rows, available_row))
# merge data, adding indicator, and filter
res = df_available.merge(df_incoming, indicator=True, how='outer')
res = res[res['_merge'] == 'right_only']
print(res)
column_name data_type table_name _merge
3 CREATE_DATE VARCHAR(20) CONFIG right_only
4 CONFIG_TYPE varchar(1) CONFIG right_only
5 CONFIG_ID numeric(10,0) CONFIG right_only
如果您需要一個字典列表作為輸出:
print(res.drop('_merge', 1).to_dict('records'))
[{'column_name': 'CREATE_DATE', 'data_type': 'VARCHAR(20)', 'table_name': 'CONFIG'},
{'column_name': 'CONFIG_TYPE', 'data_type': 'varchar(1)', 'table_name': 'CONFIG'},
{'column_name': 'CONFIG_ID', 'data_type': 'numeric(10,0)', 'table_name': 'CONFIG'}]
for incoming_d, available_d in zip(incoming_rows, available_row):
for k,v in incoming_d:
if k in available_d and available_d[k] == v:
# this key is in both dicts
else:
# something went wrong
請注意,這需要您的列表具有相同的順序。 如果順序在列表中無關緊要,那么你必須嵌套for
循環(並且復雜性變得更高)
for incoming_d in incoming_rows:
for available_d in available_rows:
...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.