簡體   English   中英

在Python中查找兩個字典列表之間的差異

[英]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.

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