2013-10-14 2 views
2

У меня есть как список:Python: удаление дубликатов из списка, сохраняя при этом порядок использования словарей

>>> a = big_list(30) 
>>> a 
[-14, -13, 10, 7, -10, 5, 3, 10, 8, -13, 14, -12, 6, 10, 8, 7, 4, -8, -10, -3, -6, 2, -6, 3, -3, 0, -13, -14, 2, -12] 

и мне нужно удалить дубликаты из Сохраняя порядка с использованием словаря

до сих пор Я преобразовал в словарь, используя этот код

def only_once(a): 
    i = iter(a) 
    print dict(zip(i,i)) 

выход был:

>>> only_once(a) 
{2: -12, 3: 10, 4: -8, 6: 10, 8: 7, 10: 7, 14: -12, -14: -13, -13: -14, -10: -3, -6: 3, -3: 0} 

Есть дубликаты, и они упорядочены в странном порядке, любые идеи о том, как преобразовать его обратно в список, сохраняя порядок и удаляя дубликаты?

+1

Посмотрите http://docs.python.org /2/library/itertools.html#recipes и рецепт 'unique_everseen'. Если вы просто удаляете дубликаты, вам не нужно помещать фактические элементы в качестве пар ключ/значение, как вы делаете ... –

+0

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

ответ

3

Используйте OrderedDict:

x = [-14, -13, 10, 7, -10, 5, 3, 10, 8, -13, 14, -12, 6, 10, 8, 7, 4, -8, -10, -3, -6, 2, -6, 3, -3, 0, -13, -14, 2, -12] 
from collections import OrderedDict 
d = OrderedDict.fromkeys(x) 
x = list(d) 

Заказ сохраняется здесь, в той мере, в первое вхождение каждого дубликата еще в том же положении.

+1

Я не уверен, что OP требует 'iter', а использование' iter (x) 'дважды в этом коде бессмысленно - это всегда просто' x' ... Также не нужно использовать '.keys() '- просто используйте' list (d) ' –

+0

Хорошо, как это :) –

+1

Нет необходимости в' zip', просто используйте 'OrderedDict.fromkeys'. Но если это ответ, тогда этот вопрос является дубликатом многих вопросов, связанных справа. – DSM

1

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

def only_once(a): 
    d = dict((b,a) for (a,b) in enumerate(a)) 
    new = d.items() 
    return [x[0] for x in sorted(new, key=lambda a: a[1])] 

Это позволит создать словарь с ключами быть элементы и ценности, которые позицию в списке, то есть первое вхождение элемента будет перезаписан более поздним возникновением (назовем reversed() для переключения такого поведения) , Затем пары (key,value) вытаскиваются из словаря, сортируются по положению в списке и усекаются только по элементам.

+0

'only_once ([1,1,1,3,3,2,2])' дает '[0, 1, 2, 5, 6, 3, 4]'. – Hyperboreus

+0

Спасибо, я забыл, каким образом работает 'enumerate'. –

2
d = {e: i for i, e in enumerate (a) } 
a = [x for x, _ in sorted(d.items(), key = lambda x: x [1]) ] 

Когда элемент отображается несколько раз в исходном списке, его последнее обнаружение сохраняется.

-1

Создайте набор элементов, которые держишь, и выбросить элементы, которые вы уже держали:

>>> a = [-14, -13, 10, 7, -10, 5, 3, 10, 8, -13, 14, -12, 6, 10, 8, 7, 4, -8, -10, -3, -6, 2, -6, 3, -3, 0, -13, -14, 2, -12] 
>>> s = set() 
>>> [ item for item in a if item not in s and s.add(item) == None] 
[-14, -13, 10, 7, -10, 5, 3, 8, 14, -12, 6, 4, -8, -3, -6, 2, 0] 

Словарь может быть использован вместо set, но это очень искусственно:

>>> d = {} 
>>> [ item for item in a if item not in d and d.update({item:None}) == None] 
[-14, -13, 10, 7, -10, 5, 3, 8, 14, -12, 6, 4, -8, -3, -6, 2, 0] 
+0

Это, к сожалению, * крайне неэффективно * (O (n^2)). Он разбивает список (O (n) на итерацию) и выполняет линейный поиск элемента (другой O (n) на итерацию). – nneonneo

+0

Изменено на решение O (n). –

+1

Вопрос заключается в том, что решение должно использовать словарь. – Stuart

0

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

first_index = {v: len(a) - 1 - i for i, v in enumerate(reversed(a))} 
print [v for i, v in enumerate(a) if i == first_index[v]] 

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

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