2015-01-07 4 views
2

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

[['john', 14, 'USA'],['john', 27, 'USA'],['paul', 17, 'USA'],['paul', 36, 'USA']] 

И нужно получить в качестве вывода:

[['john', 27, 'USA'],['paul', 36, 'USA']] 

Это означает, что для удаления дубликатов на основе позиция 0, но сохраните их с более высоким значением в позиции 1.

Я знаю, как удалить дубликаты в обычных списках, используя set(), но как я могу применить эти 2 условия? Я думал что-то с for, но я могу быть очень медленным, так как реальные списки, которые я буду использовать, очень большие.

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

Спасибо!

+0

Это очень конкретное требование, там не будет готовым решения, вы будете иметь в цикл через вещи. – dursk

ответ

1

Вы можете использовать itertools.groupby для группировки ваших элементов по первому индексу и max функции с соответствующим key выбрать макс на основе второго элемента:

>>> from itertools import groupby 
>>> l=[['john', 14, 'USA'], ['john', 27, 'USA'], ['paul', 17, 'USA'], ['paul', 36, 'USA']] 
>>> [max(g ,key=lambda x:x[1]) for _,g in groupby(sorted(l),lambda x: x[0])] 
[['john', 27, 'USA'], ['paul', 36, 'USA']] 

Или как более эффективный способ вы можете использовать operators.itemgetter() вместо lambda :

>>> from operators import itemgetter 
>>> [max(g ,key=itemgetter(1)) for _,g in groupby(sorted(l),itemgetter(0))] 
[['john', 27, 'USA'], ['paul', 36, 'USA']] 
0

Вы можете использовать OrderedDict и замените значение, если мы найдем подсписок с таким же названием с большим второй подэлементом:

l = [['john', 14, 'USA'],['john', 27, 'USA'],['paul', 17, 'USA'],['paul', 36, 'USA']] 

from collections import OrderedDict 
d = OrderedDict() 

for sub in l: 
    name = sub[0] 
    if name in d: 
     if sub[1] > d[name][1]: 
      d[name] = sub 
    else: 
     d[name] = sub 
print(list(d.values())) 

[['john', 27, 'USA'], ['paul', 36, 'USA']] 

Это O(n), поскольку он не имеет для сортировки списка, который n log n так что это будет масштабироваться лучше, чем любой метод с использованием отсортирован.

Если заказ не имеет значения, нормальный Dict будет хорошо:

d = {} 
for sub in l: 
    name = sub[0] 
    if name in d: 
     if sub[1] > d[name][1]: 
      d[name] = sub 
    else: 
     d[name] = sub 
print(d.values()) 

Если вы собираетесь сортировать с помощью operator.itemgetter будет более эффективным:

from operator import itemgetter  
sorted(l,key=itemgetter(1)) 

Если вы хотите отсортировать оригинал список:

l.sort(key=itemgetter(1)) 
1

Мне нравится решение Kasra, но jsut, чтобы дать другой способ d o это:

from collections import defaultdict 

l=[['john', 14, 'USA'], ['john', 27, 'USA'], ['paul', 17, 'USA'], ['paul', 36, 'USA']] 
key=defaultdict(list) 
for n,a,c in l: 
    key[(n,c)].append(a) 
f_list = [[k[0],max(la),k[1]] for k,la in key.iteritems()] 
0

пробующий мою руку на непонятном уровне pythonic.

используя список и словарь постижения я сортирую, сливаться, и переформатировать

a = [['john', 14, 'USA'],['john', 27, 'USA'],['paul', 17, 'USA'],['paul', 36, 'USA']] 

b = sorted(a, key=lambda x: x[0]) 
c = { x[0] : x[1:len(x)] for x in b } 

result = [[n] + c[n] for n in c] 
Смежные вопросы