2016-07-29 2 views
2

У меня есть словарь, который имеет имеет имя файла, как 1.xml, а затем DeviceIDs как 3 и 12.Список повторяющихся значений в словаре питона

{'1.xml': ['3', '12'], '2.xml': ['23', '17''], '3.xml': ['1', '12']} 

И у меня есть код, который сравнивает DeviceIDs и дисплеи когда есть дубликаты. Сейчас он работает только тогда, когда все файлы содержат DeviceID. При выполнении этого кода:

it = iter(dict.values()) 
intersection = set(next(it)) 
print(intersection) 

for vals in it: 
    intersection &= set(vals) 

возвращает

set() 

потому что DeviceID только в первом и третьем файле, но не во втором. Может ли кто-нибудь помочь мне изменить этот код, чтобы он отображал DeviceID, когда он является только дубликатом в некоторых файлах?

+0

На вашем заданном входе вывод будет ['1.xml', '3.xml'] –

ответ

3

Пересечение set сбрасывает все предыдущие дубликаты, когда новое значение в словаре не содержит их. Поэтому вместо set, вы можете использовать мультимножеством - collections.Counter - для подсчета количества раз каждый DeviceID появляется в имя_файла-DeviceId словаря:

from collections import Counter 

d = {'1.xml': ['3', '12'], '2.xml': ['23', '17'], '3.xml': ['1', '12']} 

c = Counter(i for val in d.values() for i in val) 
print(c) 
# Counter({'12': 2, '1': 1, '17': 1, '23': 1, '3': 1}) 
print(c.most_common(1)) 
# [('12', 2)] 

Если у вас есть большое количество предметов, и вы не уверены, какой номер перейти к most_common, чтобы получить дублированные идентификаторы, то вы могли бы использовать:

dupe_ids = [id for id, count in c.items() if count > 1] 
+0

избил меня, Моисей. –

+0

Просто для расширения ... '[id для id, count in c.items(), если count> 1]' –

+0

@ juanpa.arrivillaga Спасибо за это. Уже работал над этим –

1

ответ Написал Моисей я чем меньше строк кода, но это напрямую связано с вашим вопросом и может работать лучше, в зависимости от набора данных:

Причина, по которой ваш код не работает, заключается в том, что вместо &, возьмем объединение всех пересечений. Следующие обновления кода показано, как это сделать:

dev_ids = {'1.xml': ['3', '12'], '2.xml': ['23', '17'], '3.xml': ['1', '12']} 

it = iter(dev_ids.values()) 
all_ids = set(next(it)) 
dups = set() 

for vals in it: 
    vals_set = set(vals) 
    dups.update(all_ids.intersection(vals_set)) 
    all_ids.update(vals_set) 

print(dups) 

Как вы можете видеть, мы накапливаем все идентификаторы в набор - .update() по сути является операция объединения на месте - и выполнять перекрестки на ней, как мы идти. Каждое пересечение можно рассматривать как «дубликаты», содержащиеся в этом файле. Мы накапливаем дубликаты в переменной dup, и это становится нашим ответом.

+0

Спасибо за отличную информацию, не забудьте ее запомнить – Jan