2015-01-15 4 views
0

У меня есть словарь, как это:Python удалить повторяющиеся значения одного ключа в Словаре

Files: 
{'key1': ['path1', 'path1', 'path2', 'path1', 'path2'], 
'key2': ['f', 'f', 'f', 'f', 'f'], 
'key_file': ['file1', 'file1', 'file2', 'file1', 'file2']} 

Я хочу, чтобы удалить все повторяющиеся значения унда в «KEY_FILE» и других их значение в других клавишах ('key1 'и' key2 ').

Желаемая словарь:

Files: 
{'key1': ['path1', 'path2'], 
'key2': ['f', 'f'], 
'key_file': ['file1', 'file2']} 

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

Большое спасибо.

EDIT:

'key2': ['f', 'f', 'f', 'f', 'f'] 

становится

'key2': ['f', 'f'], 

, потому что есть два различных файла.

Я не хочу удалять каждый дубликат в каждом ключе. «path1» связан с «file1», а «path2» связан с «file2», как и «f» в key2 для обоих случаев. На самом деле в действительности есть несколько ключей больше, но это мой минимальный пример. Это моя проблема. Я нашел несколько решений для удаления каждого дубликата.

EDIT2:

Может быть, я был немного сбивает с толку.

Каждый ключ имеет ту же длину, что и имя файла (в ключевом файле), соответствующий путь (в ключе1) и некоторые другие описывающие строки (в key2 и т. Д.). Может случиться так, что тот же файл хранится в разных местах (путях), но я знаю, что это тот же файл, если имя файла точно такое же.

В основном то, что я искал, является функцией, которая определяет второе значение key_file с файлом filename1 как дубликат первого файла значений1 и удаляет второе значение из каждого ключа. То же самое для значения 4 (файл1) и 5 ​​(файл2). В результате словарь будет выглядеть так, как я упомянул.

Надеюсь, это объяснит это лучше.

+1

'[ 'е', 'е', 'е', 'е', 'е'] 'становится' ['f', 'f'] '? – thefourtheye

+0

Чтобы удалить дубликаты, см. Этот вопрос: http://stackoverflow.com/questions/480214/how-do-you-remove-duplicates-from-a-list-in-python-whilst-preserving-order Помимо этого, это просто петля через элементы dict :) – Wolph

+1

@thefourtheye Да, посмотрите на отредактированный текст. – Keynaan

ответ

2

наивный подход: перебирать ключи и добавить новый Словаре каждый значения:

>>> newFiles={'key1': [], 'key2':[], 'key_file':[]} 
>>> for i,j in enumerate(Files['key_file']): 
... if j not in newFiles['key_file']: 
...  for key in newFiles.keys(): 
...   newFiles[key].append(Files[key][i]) 
... 
>>> newFiles 
{'key2': ['1', '3'], 'key1': ['a', 'c'], 'key_file': ['file1', 'file2']} 

с OrderedDict:

>>> for j in OrderedDict.fromkeys(Files['key_file']): 
... i = Files['key_file'].index(j) 
... if j not in newFiles['key_file']: 
...  for key in newFiles.keys(): 
...  newFiles[key].append(Files[key][i]) 
... 
>>> newFiles 
{'key2': ['1', '3'], 'key1': ['a', 'c'], 'key_file': ['file1', 'file2']} 

Примечание: если "файл" в key_file всегда имеет один и тот же key_1 и key_2, есть более эффективные способы. Например, используя zip:

>>> z=zip(*Files.values()) 
>>> z 
[('f', 'path1', 'file1'), ('f', 'path1', 'file1'), ('f', 'path2', 'file2'), ('f', 'path1', 'file1'), ('f', 'path2', 'file2')] 
>>> OrderedDict.fromkeys(z) 
OrderedDict([(('f', 'path1', 'file1'), None), (('f', 'path2', 'file2'), None)]) 
>>> list(OrderedDict.fromkeys(z)) 
[('f', 'path1', 'file1'), ('f', 'path2', 'file2')] 
>>> zip(*OrderedDict.fromkeys(z)) 
[('file1', 'file2'), ('path1', 'path2'), ('f', 'f')] 
+0

Большое спасибо. Это похоже на решение, которое я искал. – Keynaan

+1

Что делать, если есть триплет записей с одним и тем же ключом 'key_file', но с разными' key1' или 'key2'? –

+0

@tobias_k не думал об этом случае. Не уверен, что это может произойти. Я попросил ОП разъяснить. – fredtantini

1

OrderedDict является лучшим, как она поддерживает порядок

Вы можете добавить его в набор, а затем сделать его список

Пример

for i in d: 
    d[i] = list(set(d[i])) 
+0

Почему downvotes bro ??? Мой ответ плохой? –

1

Вы можете использовать collections.OrderedDict держать словарь в для заказа и set удалить дубликаты:

>>> d={'key1': ['path1', 'path1', 'path2', 'path1', 'path2'], 
... 'key2': ['f', 'f', 'f', 'f', 'f'], 
... 'key_file': ['file1', 'file1', 'file2', 'file1', 'file2']} 
>>> from collections import OrderedDict 
>>> OrderedDict(sorted([(i,list(set(j))) for i,j in d.items()], key=lambda t: t[0])) 
OrderedDict([('key1', ['path2', 'path1']), ('key2', ['f']), ('key_file', ['file2', 'file1'])]) 

вам нужно использовать set для значений, чтобы удалить дубликаты, а затем сортировать элементы на основе ключей и, наконец, сохранить словарь в сортировке OrderedDict.

Edit: если вы хотите, чтобы все значения имеют одинаковую длину, а максимальное значение используйте следующее:

>>> s=sorted([(i,list(set(j))) for i,j in d.items()], key=lambda t: t[0]) 
>>> M=max(map(len,[i[1] for i in s]) 
>>> f_s=[(i,j) if len(j)==M else (i,[j[0] for t in range(M)]) for i,j in s] 
>>> f_s 
[('key1', ['path2', 'path1']), ('key2', ['f', 'f']), ('key_file', ['file2', 'file1'])] 
>>> OrderedDict(f_s) 
OrderedDict([('key1', ['path2', 'path1']), ('key2', ['f', 'f']), ('key_file', ['file2', 'file1'])]) 

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

>>> OrderedDict(sorted([(i,j[:2]) for i,j in d.items()],key=lambda x: x[0]) 
...) 
OrderedDict([('key1', ['path1', 'path1']), ('key2', ['f', 'f']), ('key_file', ['file1', 'file1'])]) 
+0

Благодарим вас за быстрый ответ. Я редактировал мой вопрос выше. Я забыл упомянуть, что хочу сохранить длину каждого ключа. – Keynaan

+0

@ Keynaan приветствую, поэтому вы хотите, чтобы все значения имели одинаковую длину с длинным значением? – Kasramvd

+0

В этом случае я хочу 2 значения в каждом ключе. @fretantini ответил, но спасибо. – Keynaan

0

Как я понимаю, этот вопрос, кажется, что соответствующие значения в различных списках в словаре принадлежат вместе, в то время как значения в том же списке не имеют никакого отношения друг к другу. В этом случае я бы предложил использовать другую структуру данных. Вместо того, чтобы иметь словарь с тремя списками элементов, вы можете сделать один список, содержащий триплеты.

>>> files = {'key1': ['path1', 'path1', 'path2', 'path1', 'path2'], 
      'key2': ['f', 'f', 'f', 'f', 'f'], 
      'key_file': ['file1', 'file1', 'file2', 'file1', 'file2']} 
>>> files2 = set(zip(files["key1"], files["key2"], files["key_file"])) 
>>> print files2 
set([('path2', 'f', 'file2'), ('path1', 'f', 'file1')]) 

Или, если вы хотите, чтобы сделать его более словарю, как вы могли бы сделать это, потом:

>>> files3 = [{"key1": k1, "key2": k2, "key_file": kf} for k1, k2, kf in files2] 
>>> print files3 
[{'key2': 'f', 'key1': 'path2', 'key_file': 'file2'}, 
{'key2': 'f', 'key1': 'path1', 'key_file': 'file1'}] 

Обратите внимание, что порядок троек в списке верхнего уровня могут отличаться друг от друга, но элементы, которые принадлежат друг другу, все еще объединены в содержащиеся кортежи или словари.

0

Вот моя реализация:

In [1]: mydict = {'key1': ['path1', 'path1', 'path2', 'path1', 'path2'], 'key2': ['f', 'f', 'f', 'f', 'f'], 'key_file': ['file1', 'file1', 'file2', 'file1', 'file2']} 

In [2]: { k: sorted(list(set(v))) for (k,v) in mydict.iteritems() } 
Out[2]: {'key1': ['path1', 'path2'], 'key2': ['f'], 'key_file': ['file1', 'file2']} 

Тест

In [6]: mydict 
Out[6]: 
{'key1': ['path1', 'path1', 'path2', 'path1', 'path2'], 
'key2': ['f', 'f', 'f', 'f', 'f'], 
'key_file': ['file1', 'file1', 'file2', 'file1', 'file2']} 

In [7]: uniq = { k: sorted(list(set(v))) for (k,v) in mydict.iteritems() } 

In [8]: for key in uniq: 
    ...:  print 'KEY :', key 
    ...:  print 'VALUE :', uniq[key] 
    ...:  print '-------------------' 
    ...: 
KEY : key2 
VALUE : ['f'] 
------------------- 
KEY : key1 
VALUE : ['path1', 'path2'] 
------------------- 
KEY : key_file 
VALUE : ['file1', 'file2'] 
-------------------