Python удаляет дубликаты - PullRequest
2 голосов
/ 09 марта 2011

В массиве у меня есть следующие кортежи:

<code>  ('0000233/02', 50.0, None, None, None, None, 'Yes') 
  ('0000233/02', 200.0, None, None, None, None, 'Yes') 

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

Ответы [ 6 ]

3 голосов
/ 09 марта 2011

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

1 голос
/ 09 марта 2011

Немного другим способом, если ваш вход отсортирован (или, по крайней мере, с дубликатами, объединенными вместе), является использование itertools.groupby:

import itertools, operator

def filter_duplicates(items):
    for key, group in itertools.groupby(items, operator.itemgetter(0)):
        yield next(group)

Выбирает первый элемент каждого скопления дубликатов (группировка по первому элементу). Это более эффективно, чем подходы, основанные на множестве / дикте, поскольку никакой дополнительной структуры не требуется, и сохраняется порядок последовательности. Однако это зависит от дубликатов, поступающих партиями - если они могут появиться где-либо в потоке, используйте один из других методов.

1 голос
/ 09 марта 2011

Специальное решение:

def unique_elem0( iterable ):
    seen = set()
    seen_add = seen.add
    for element in iterable:
        key = element[0]
        if key not in seen:
            seen_add(key)
            yield element

print list(unique_elem0(lst))

«Скопируйте код из рецептов itertools »:

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

from operator import itemgetter        
print list(unique_everseen(lst, key=itemgetter(0)))
1 голос
/ 09 марта 2011

Смотри сначала: http://docs.python.org/faq/programming.html#how-do-you-remove-duplicates-from-a-list

>>> l=[('0000233/02', 50.0, None, None, None, None, 'Yes'), ('0000233/02', 200.0, None, None, None, None, 'Yes') ]
>>> dic={}
>>> for i in l: dic[i[0]]=i
...   
>>> dic
{'0000233/02': ('0000233/02', 200.0, None, None, None, None, 'Yes')}
>>> list(dic.values())
[('0000233/02', 200.0, None, None, None, None, 'Yes')]
0 голосов
/ 10 марта 2011

Если вы НЕ заботитесь о порядке элементов после первого, это быстро и просто:

>>> t1= ('0000233/02', 50.0, None, None, None, None, 'Yes')
>>> t2= ('0000233/02', 200.0, None, None, None, None, 'Yes')
>>> t1=(t1[0],)+tuple(set(t1[1:]))
>>> t2=(t2[0],)+tuple(set(t2[1:]))
>>> t1
('0000233/02', 50.0, None, 'Yes')
>>> t2
('0000233/02', 200.0, 'Yes', None)

Если вы НЕ заботитесь о порядке:

>>> t2= ('0000233/02', 200.0, None, None, None, None, 'Yes')
>>> nd=[]
>>> garbage=[nd.append(i) for i in t2 if not nd.count(i)]
>>> t2=tuple(nd)
>>> t2
('0000233/02', 200.0, None, 'Yes')
0 голосов
/ 09 марта 2011

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

# This will leave the last tuple found with that 1st value in the dict:
d = {}
for t in tuples:
    d[t[0]] = t # or .set()

# This will leave the first tuple found, instead of the last:
d = {}
for t in tuples:
    d.setdefault(t[0], t) # setdefault sets the value if it's missing.
...