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

1

Я пытаюсь удалить все дубликаты и оригиналы из вложенного списка на основе определенного столбца.

пример

list = [['abc',3232,'demo text'],['def',9834,'another text'],['abc',0988,'another another text'],['poi',1234,'text']]

Ключевой столбец - первый (abc, def, abc), и на основе этого я хочу удалить любой элемент (плюс оригинал), который имеет то же значение с оригиналом.

Поэтому новый список должен содержать:

newlist = [['def',9834,'another text'],['poi',1234,'text']]

Я нашел много похожих тем, но не для вложенных списков... Любая помощь, пожалуйста?

Теги:
list
duplicates
nested-lists

4 ответа

1
Лучший ответ

Используйте collections.Counter:

from collections import Counter

lst = [['abc',3232,'demo text'],['def',9834,'another text'],['abc',988,'another another text'],['poi',1234,'text']]

d = dict(Counter(x[0] for x in lst))
print([x for x in lst if d[x[0]] == 1])

# [['def', 9834, 'another text'], 
#  ['poi', 1234, 'text']]

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

  • 1
    Хорошее решение, это имеет сложность O (n). Но я не думаю, if x[0] in d.keys() необходим?
  • 0
    @jpp упс! Это не обязательно. Большое спасибо.
2

Вы можете создать список ключей

keys = [x[0] for x in list]

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

newlist = [x for x in list if keys.count(x[0]) == 1]
  • 0
    Вы имеете O (n ^ 2) сложность здесь, вызывая list.count n раз. Вы можете использовать collections.Counter чтобы сделать это O (n). Или хранить ваши счета отдельно.
  • 0
    Что ж, OP ничего не сказал относительно размера списка, поэтому я предположил, что он недостаточно велик, чтобы сделать разницу между O (n) и O (n ^ 2). Определенно, использование Counter является более эффективным подходом, но я намеревался дать быстрое и грязное решение, которое хорошо работает в большинстве случаев.
Показать ещё 2 комментария
1

Использование collections.defaultdict для решения O (n):

L = [['abc',3232,'demo text'],
     ['def',9834,'another text'],
     ['abc',988,'another another text'],
     ['poi',1234,'text']]

from collections import defaultdict

d = defaultdict(list)

for key, num, txt in L:
    d[key].append([num, txt])

res = [[k, *v[0]] for k, v in d.items() if len(v) == 1]

print(res)

[['def', 9834, 'another text'],
 ['poi', 1234, 'text']]
  • 0
    Между этим решением тоже хорошо. Я обычно иду на Counter чем путь по defaultdict . +1.
1

Использование понимания списка.

Демо - версия:

l = [['abc',3232,'demo text'],['def',9834,'another text'],['abc', 988,'another another text'],['poi',1234,'text']]
checkVal = [i[0] for i in l]
print( [i for i in l if not checkVal.count(i[0]) > 1 ] )

Выход:

[['def', 9834, 'another text'], ['poi', 1234, 'text']]
  • 0
    Вы имеете O (n ^ 2) сложность здесь, вызывая list.count n раз. Вы можете использовать collections.Counter чтобы сделать это O (n). Или хранить ваши счета отдельно.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню