2016-04-22 2 views
2

Я пытаюсь найти разницу между двумя списками словаря. Я нашел некоторую информацию на этом форуме, но не выполнил свою задачу.Найти разницу между двумя списками словаря в Python

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 словаря и разница хочу перечислить в другом списке Словаре format.Here мое имя таблицы является уникальным. Условия: 1. Любое новое добавление столбцов. 2. Любые изменения в типе данных Если эти два условия истинны, то ожидаемый_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

находят пересечение 2 списка. это может помочь: http://stackoverflow.com/questions/642763/python-intersection-of-two-lists –

+0

@csessh, так как мы пытаемся найти пересечение списка *, заполненного несмонтируемыми объектами *, эта ссылка есть в основном неактуальны. (например, try 'set(). add ({" some ":" dict "})') –

ответ

3

Набор является идеальным решением для этой задачи. К сожалению, 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')})} 

Edit: Разморозить:

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'}] 
+0

Я никогда не слышал о «замораживании» элемента раньше! Не могли бы вы немного объяснить, что это? благодаря! –

+0

Фризонсет - неизменяемый тип набора в Python (например, вы не можете делать 'frozenset.add (...)' или и т. Д.). Поскольку он неизменен, он (здраво) hashable, поэтому вы можете поместить его в набор. –

+0

это то, что я искал. спасибо @ Neal Fultz – Pradeep

-1
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: 
     ... 
Смежные вопросы