2015-07-17 2 views
5

У меня есть список, содержащий списки, и вам нужен быстрый способ дедуплирования списков.Самый быстрый способ дедуплексного списка в dict

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

hello = {'test1':[2,3,4,2,2,5,6], 'test2':[5,5,8,4,3,3,8,9]} 

Я хочу, чтобы это выглядело как;

hello = {'test1':[2,3,4,5,6], 'test2':[5,8,4,3,9]} 

Хотя я не обязательно должен иметь первоначальный порядок сохраненных списков.

Я попытался с помощью набора, как это, но это не совсем правильно (это не перебор должным образом, и я теряю первый ключ)

for key, value in hello.items(): goodbye = {key: set(value)} 
>>> goodbye 
{'test2': set([8, 9, 3, 4, 5])} 

EDIT: После комментария PM 2Ring в ниже, Я теперь заполняю диктовку иначе, чтобы избежать дублирования в первую очередь. Раньше я использовал списки, но использование наборов предотвращает добавление дубликатов по умолчанию;

>>> my_numbers = {} 
>>> my_numbers['first'] = [1,2,2,2,6,5] 
>>> from collections import defaultdict 
>>> final_list = defaultdict(set) 
>>> for n in my_numbers['first']: final_list['test_first'].add(n) 
... 
>>> final_list['test_first'] 
set([1, 2, 5, 6]) 

Как вы можете видеть, конечный выход представляет собой деблокированный набор, если требуется.

+2

не заинтересован в сохранении порядка, а также мои списки часть диктата. –

+2

Если вам не нужно сохранять порядок, то перейдите на подход, основанный на наборе: он более эффективен, чем подходы, основанные на списках, но вы можете не заметить большую разницу в скорости, если ваши списки невелики или если у них мало обманов , И подумайте о хранении наборов, а не о списках в качестве значений вашего dict. OTOH, для _very_ маленьких списков метод на основе набора может быть _slower_. Кроме того, наборы используют немного больше памяти, чем списки. –

+0

@ PM2Ring Я пошел с использованием наборов в конце, поэтому избегал обманов в первую очередь. defaultdict (set) и .add (n), чтобы добавить к набору, сделали трюк. Q обновлено. –

ответ

4

Это не перебор неправильно, вы просто назначая до свидания, как новый Словаре каждый раз. Вы должны назначить в качестве пустого dict, а затем назначить значения клавишам на каждой итерации.

goodbye = {} 
for key, value in hello.items(): goodbye[key] = set(value) 
>>> goodbye 
{'test1': set([2, 3, 4, 5, 6]), 'test2': set([8, 9, 3, 4, 5])} 

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

def uniqueList(li): 
    newList = [] 
    for x in li: 
     if x not in newList: 
      newList.append(x) 
    return newList 


goodbye = {} 
for key, value in hello.items(): goodbye[key] = uniqueList(value) 
>>> goodbye 
{'test1': [2, 3, 4, 5, 6], 'test2': [5, 8, 4, 3, 9]} 
+1

Я предполагаю, что это одна из причин, по которой О.П. сказал, что его решение «не совсем корректно», и порядок сохраняется в списках (!) В ожидаемом выходе. –

+0

OP здесь. Собственно, сохранение порядка не имеет значения. Таким образом, этот подход отлично подходит для моих целей. Мое решение было не совсем правильным, потому что я назначал новое значение вместо добавления, оставив только один ключ. –

+0

Добавил решение для сохранения второго порядка в любом случае ради полноты. – SuperBiasedMan

5

Вы можете использовать список понимание с deduplicate функции, которая сохраняет порядок:

def deduplicate(seq): 
    seen = set() 
    seen_add = seen.add 
    return [ x for x in seq if not (x in seen or seen_add(x))] 

{key: deduplicate(value) for key, value in hello.items()} 
+0

Как раз как примечание: ошибки dict не работают со старыми версиями Python, такими как 2.7. – Daniel

+1

@ Daniel работает в Python 2.7, он не работает ни в одной версии старше этого. –

+0

@AnandSKumar Вы правы. Я это испортил. – Daniel

0

Это более многословный способ сделать это, сохраняющий порядок и работает во всех версиях Python:

for key in hello: 
    s = set() 
    l = [] 
    for subval in hello[key]: 
     if subval not in s: 
      l.append(subval) 
      s.add(subval) 
    hello[key] = l 
0
my_list = [1,2,2,2,3,4,5,6,7,7,7,7,7,8,9,10] 
seen = set() 
print list(filter(lambda x:x not in seen and not seen.add(x),my_list)) 
3
>>>hello = {'test1':[2,3,4,2,2,5,6], 'test2':[5,5,8,4,3,3,8,9]}  
>>>for key,value in hello.iteritems(): 
     hello[key] = list(set(value)) 
>>>hello 
{'test1': [2, 3, 4, 5, 6], 'test2': [8, 9, 3, 4, 5]} 
+1

Ах круто, что превращает «набор» в список. –

Смежные вопросы