2012-05-21 4 views
1

Am ищет чистый вещий способ сделать следующийфильтрация списка кортежей в Python

У меня есть список кортежей сказать:

[(1,'a'), (1,'b'), (1,'c'), (2, 'd'), (5, 'e'), (5, 'f')] 

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

[(1,'c'), (2,'d'), (5, 'f')] 

Спасибо!

+2

Хм, ваш пример, похоже, не соответствует описание. – georg

ответ

4

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

In [1]: l = [(1,'a'), (1,'b'), (1,'c'), (2, 'd'), (5, 'e'), (5, 'f')] 

In [2]: dict(l).items() 
Out[2]: [(1, 'c'), (2, 'd'), (5, 'f')] 

Update: Как @Tadeck упоминает в своем комментарии, так как порядок словарных элементов не гарантируется, вы, вероятно, хотите использовать ordered dictionary:

from collections import OrderedDict 
newl = OrderedDict(l).items() 

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

+0

На самом деле я считаю, что это должен быть 'OrderedDict' вместо простого' dict', и вы должны преобразовать 'l [:: - 1]' (или 'reverseed (l)') вместо 'l'. Таким образом, будет удовлетворено требование ФП («кортежи _discards, чей первый ключ был замечен раньше»), и порядок будет сохранен. – Tadeck

+0

@Tadeck: Хорошая точка относительно 'OrderedDict'. Что касается формулировки вопроса, я думаю, что это неоднозначно. Если он хотел сохранить '[(1, 'a'), (2, 'd'), (5, 'e')]', то да, можно просто отменить список. –

+0

Если вы отмените список, то использование 'OrderedDict' не поможет сохранить заказ. Однако ОП смущает то, что они хотят. – Duncan

2

unique_everseen Использование из itertoolsdocs

from itertools import ifilterfalse 
def unique_everseen(iterable, key=None): 
    "List unique elements, preserving order. Remember all elements ever seen." 
    # unique_everseen('AAAABBBCCDAABBB') --> A B C D 
    # unique_everseen('ABBCcAD', str.lower) --> A B C D 
    seen = set() 
    seen_add = seen.add 
    if key is None: 
     for element in ifilterfalse(seen.__contains__, iterable): 
      seen_add(element) 
      yield element 
    else: 
     for element in iterable: 
      k = key(element) 
      if k not in seen: 
       seen_add(k) 
       yield element 

a = [(1,'a'), (1,'b'), (1,'c'), (2, 'd'), (5, 'e'), (5, 'f')] 

print list(unique_everseen(a,key=lambda x: x[0])) 

Уступая

[(1, 'a'), (2, 'd'), (5, 'e')] 
2

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

>>> s = [(1,'a'), (1,'b'), (1,'c'), (2, 'd'), (5, 'e'), (5, 'f')] 
>>> seen = set() 
>>> [seen.add(x[0]) or x for x in s if x[0] not in seen] 
[(1, 'a'), (2, 'd'), (5, 'e')] 
Смежные вопросы