我试图找到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'}
]
答案 0 :(得分:5)
一套是这个问题的完美解决方案。不幸的是,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'}]
答案 1 :(得分:0)
对于大型数据集,尤其是在处理数字数据时,使用第三方库可能会发现更好的性能。例如,熊猫直接接受目录列表:
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'}]
答案 2 :(得分:-2)
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:
...