2014-10-10 4 views
1

У меня есть следующая проблема: заданы два dicts с идентификаторами товара в виде ключей и title + author в качестве значений. Я хотел бы сравнить два dicts, используя идентификаторы статьи: если у идентификаторов статьи есть разные заголовки/авторы, я бы хотел создать сопоставление, состоящее из строки, которая сначала выводит старый идентификатор статьи, а также заголовок и автора И новый идентификатор с соответствующим заголовком и автором.Python: найти отличия в двух dicts

Пример:

old = {u'2014_en_1': u'Letter A\tauthor A\n', u'2014_en_2': u'Explanation\tauthor B\n', u'2014_en_3': u'Conclusion\tauthor C\n'} 
new = {u'2014_en_1': u'Welcome\tauthor XY\n', u'2014_en_2': u'Letter A\tauthor A\n', u'2014_en_3': u'Conclusion\tauthor C\n', u'2014_en_4': u'Explanation\tauthor B\n',} 

for k, v in old.iteritems(): 
    if old[k] != new[k]: 
     print k + "\t" + old[k] + # HOW can I find the corresponding article in new? 

Таким образом, желаемый результат должен быть:

[] [] 2014_en_1 Welcome\tauthor XY 
2014_en_1 Letter A\tauthor A 2014_en_2 Letter A\tauthor A 
2014_en_2 Explanation\tauthor B 2014_en_4 Explanation\tauthor B 
2014_en_3 Conclusion\tauthor C 2014_en_3 Conclusion\tauthor C 

Как я могу это сделать? Это сложно, потому что возможно, что новый dict может иметь новые статьи (или наоборот):/ Спасибо за любую помощь!

ответ

0

Это проще, если вы изменить ваш old отображение таким образом, чтобы значения (название, авторы) становятся ключами вместо.

Тогда вы можете просто перебирать new и попытаться соответствовать идентификаторам:

old_reverse = {v: k for k, v in old.items()} 
for k, v in new.iteritems(): 
    try: 
     old_k = old_reverse[v] 
     print "%s\t%s\t%s\t%s" % (old_k, repr(v), k, repr(v),) 
    except KeyError: 
     print "[]\t[]\t%s\t%s" % (k, repr(v),) 

Обратите внимание, что я использовал repr сделать вывод немного более удобным для чтения. Вместо этого вы можете применить некоторые собственные манипуляции со строками, чтобы получить желаемый формат вывода.

Словари - это несортированные коллекции в Python. Если вы хотите, чтобы они сортируются, вы можете использовать дополнительный шаг, сохраняя вывод в список кортежей, а затем распечатать его отсортирован:

# Flip the dict 
old_reverse = {v: k for k, v in old.items()} 

# Map new VS old 
data = [] 
for k, v in new.iteritems(): 
    try: 
     old_k = old_reverse[v] 
     data.append((old_k, v, k, v,)) 
    except KeyError: 
     data.append((None, None, k, v,)) 

# Print them sorted 
for old_k, old_v, k, v in sorted(data, key=lambda d: d[0]): 
    print "%s\t%s\t%s\t%s" % (
     old_k if old_k is not None else "[]", 
     repr(old_v) if old_k is not None else "[]", 
     k, 
     repr(v), 
    ) 
+0

Спасибо большое за предложение! :) Это именно то, что я хотел сделать! И ... ничего себе, всего в 7 строках! : O Что я хотел спросить: возможно ли получить выходной вид сортировки, возможно, s.t. сначала печатаются новые статьи без переписки в старом dict, а после art_1 из старого dict, который принадлежит статье X в новом dict? – MarkF6

+0

@ MarkF6: Это возможно, но это включает дополнительный шаг, на котором вы храните данные в списке и распечатываете их отсортированные. См. Обновленный ответ. – netcoder

+0

WOW, это феноменально! :) Большое спасибо! :) – MarkF6

0
# Get all keys 
keys = set(old.keys()).union(set(new.keys())) 

# Reverse the new dict 
new_reverse = {v:k for k,v in new.items()} 

# Loop keys and output 
for k in keys: 
    if k in old: 
     if old[k] != new[k]: 
      v = old[k] 
      k_in_new = new_reverse[v] 
      v_in_new = new[k_in_new] 
     else: 
      k_in_new = k 
      v_in_new = v 

     print '%s %s %s %s' % (k, old[k], k_in_new, v_in_new) 
    else: 
     print '[] [] %s %s' % (k, new[k]) 
Смежные вопросы