2016-02-17 5 views
0
t = [[a, b], [c, d], [a, e], [f, g], [c, d]] 

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

output = [[a, b], [c, d], [a, e], [f, g]] 

[с, d] присутствует дважды, она должна быть удалена , [a, b] и [a, e] являются уникальными списками, независимо от дублированного «a».

Спасибо!

+0

Что '' b' и c'? Являются ли они простыми значениями или другими 'list',' dict'? –

+1

Это вопрос порядка? –

+4

Возможный дубликат [Как удалить дубликаты из списка в Python при сохранении заказа?] (Http://stackoverflow.com/questions/480214/how-do-you-remove-duplicates-from-a-list-in -python-while-preserve-order), [Python удаляет дубликаты в списках] (http: // stackoverflow.com/questions/7961363/python-remove-duplicates-in-lists) – GingerPlusPlus

ответ

3

OrderedDict сохранит порядок и предоставит вам уникальные элементы, как только мы сопоставим подсписок с кортежами, чтобы сделать их хешируемыми, используя t[:], чтобы мы могли изменить исходный объект/список.

t = [["a", "b"], ["c", "d"], ["a", "e"], ["f", "g"], ["c", "d"]] 

from collections import OrderedDict 

t[:] = map(list, OrderedDict.fromkeys(map(tuple, t))) 

print(t) 
[['a', 'b'], ['c', 'd'], ['a', 'e'], ['g', 'f']] 

Для python2 вы можете использовать itertools.imap, если вы хотите, чтобы избежать создания промежуточных списков:

from collections import OrderedDict 
from itertools import imap 

t[:] = imap(list, OrderedDict.fromkeys(imap(tuple, t))) 

print(t) 

Вы также можете использовать set.add or логику:

st = set() 

t[:] = (st.add(tuple(sub)) or sub for sub in t if tuple(sub) not in st) 

print(t) 

Какой бы самый быстрый подход :

In [9]: t = [[randint(1,1000),randint(1,1000)] for _ in range(10000)] 

In [10]: %%timeit              
st = set() 
[st.add(tuple(sub)) or sub for sub in t if tuple(sub) not in st] 
    ....: 
100 loops, best of 3: 5.8 ms per loop 

In [11]: timeit list(map(list, OrderedDict.fromkeys(map(tuple, t)))) 
10 loops, best of 3: 24.1 ms per loop 

Кроме того, если ["a","e"] считается такой же, как ["e","a"] вы можете использовать frozenset:

t = [["a", "b"], ["c", "d"], ["a", "e"], ["f", "g"], ["c", "d"], ["e","a"]] 
st = set() 
t[:] = (st.add(frozenset(sub)) or sub for sub in t if frozenset(sub) not in st) 

print(t) 

Выход:

[['a', 'b'], ['c', 'd'], ['a', 'e'], ['f', 'g']] 

Чтобы избежать двух вызовов кортежа вы можете сделать функцию:

def unique(l): 
    st, it = set(), iter(l) 
    for tup in map(tuple, l): 
     if tup not in st: 
      yield next(it) 
     else: 
      next(it) 
     st.add(tup) 

, который работает немного быстрее:

In [21]: timeit list(unique(t)) 
100 loops, best of 3: 5.06 ms per loop 
-1

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

t = [["a", "b"], ["c", "d"], ["a", "e"], ["f", "g"], ["c", "d"]] 
i = len(t) - 1 
while i >= 0: 
    if t.count(t[i]) > 1: 
     t.pop(i) 
    i -= 1 
print(t) 
+0

Не знаете, почему ваш ответ сработал! – Tom

0

Вы можете сделать это с помощью set (если порядок внутренних списков не имеет значения):

>>> t = [['a', 'b'], ['c', 'd'], ['a', 'e'], ['f', 'g'], ['c', 'd']] 
>>> as_tuples = [tuple(l) for l in t] 
>>> set(as_tuples) 
{('a', 'b'), ('a', 'e'), ('c', 'd'), ('f', 'g')} 
0

Простой подход, предполагающий, что вы не хотите создавать новые списки и минимизировать выделение.

# Assumption; nested_lst contains only lists with simple values (floats, int, bool) 
def squashDups(nested_lst): 
    ref_set = set() 
    new_nested_lst = [] 
    for lst in nested_lst: 
     tup = tuple(lst) 
     if tup not in ref_set: 
      new_nested_lst.append(lst) 
      ref_set.add(tup) 
    return new_nested_lst 

>>> lst = [ [1,2], [3,4], [3,4], [1,2], [True,False], [False,True], [True,False] ] 
>>> squashDups(lst) 
[[1, 2], [3, 4], [True, False], [False, True]] 
2

Простое решение

t = [["a", "b"], ["c", "d"], ["a", "e"], ["f", "g"], ["c", "d"]] 
output = [] 

for elem in t: 
    if not elem in output: 
     output.append(elem) 

print output 

Выход

[['a', 'b'], ['c', 'd'], ['a', 'e'], ['f', 'g']]