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

У меня есть список:

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

И нужно получить результат:

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

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

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

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

Благодаря!

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

 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()] 

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

 >>> 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']] 

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

использование списков и словарных знаний i сортировка, слияние и переформатирование

 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] 

Вы можете использовать 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 поэтому это будет масштабироваться лучше, чем любой метод с использованием отсортированного.

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

 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))