1

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

def filterList(stringList, string)

Она будет вызываться так:

filterList(['cat', 'hello', 'dog', 'hello'], 'hello')  

надо получить

[‘cat’, ‘dog’]

Используется Python 3.5

insolor
  • 49,104

3 Answers3

1

Добавлю от себя примеры.

  • filter_list – стандартный алгоритм

  • filter_list_2 – стандартный алгоритм, переделанный в синтаксис генератора списка

  • filter_list_3 – использование функции фильтрации, которая будет применяться к каждому элементу

Код:

def filter_list(items, value):
    has_more = items.count(value) > 1
    new_items = []
for x in items:
    # Если встретили элемент и он встречается больше одного раза
    if x == value and has_more:
        continue

    new_items.append(x)

return new_items


def filter_list_2(items, value): has_more = items.count(value) > 1 return [x for x in items if not (x == value and has_more)]

def filter_list_3(items, value): has_more = items.count(value) > 1 return list(filter(lambda x: not (x == value and has_more), items))

if name == 'main': items = ['cat', 'hello', 'dog', 'hello'] print(filter_list(items, 'hello')) print(filter_list_2(items, 'hello')) print(filter_list_3(items, 'hello'))

print()

print(filter_list(items, 'cat'))
print(filter_list_2(items, 'cat'))
print(filter_list_3(items, 'cat'))

Консоль:

['cat', 'dog']
['cat', 'dog']
['cat', 'dog']

['cat', 'hello', 'dog', 'hello'] ['cat', 'hello', 'dog', 'hello'] ['cat', 'hello', 'dog', 'hello']

gil9red
  • 77,085
  • items.count(value) > 1 желательно из цикла вытащить во всех трех вариантах. В данном случае, конечно, не сильно заметно будет, но вообще эта проверка превращает O(n) в O(n^2). – insolor Aug 13 '17 at 05:58
  • @insolor, подправил – gil9red Aug 13 '17 at 08:56
1

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

def filterList(stringList, string):
    if stringList.count(string) > 1:
        return [s for s in stringList if s != string]
    return list(stringList)

Это линейный алгоритм (по числу сравнений элементов), который сохраняет порядок элементов в списке. Исходный список всегда без изменений остаётся.

Можно по месту удалить (заодно переходя на PEP-8 имена):

def remove_if_non_uniq(lst, item):
    if lst.count(item) > 1:
        remove_all(lst, item)

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

jfs
  • 52,361
0

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

from collections import Counter

z = ['cat', 'hello', 'dog', 'hello']
print ([k for (k, v) in Counter(z).items() if v == 1])

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

from collections import Counter

z = ['cat', 'hello', 'dog', 'hello', 'dog', 'parrot']
def filterList(l, s):
    return list(set(l) - set([k for (k, v) in Counter(l).items() if v > 1 and s in k]))

print (filterList(z, 'hello'))
Lex Hobbit
  • 4,306
  • 1
    В set генератор списка можно заменить просто на генератор, пример: set([k for k, v in items]) -> set(k for k, v in items) – gil9red Aug 12 '17 at 03:56
  • 1- первый пример не сохраняет порядок элементов в списке (Counter не упорядочен в Питоне). Чтобы сохранить порядок, поправьте условие в коде 2- второй пример: сразу несколько вещей неверны. Подумайте, что вы бы хотели получить, к примеру, для filterList(['cat', 'dog', 'hello', 'cat', 'hello'], 'hello')? Сравните результаты – jfs Aug 13 '17 at 07:20
  • @jfs про порядок ничего не сказано, что во втором неверно? задачу выполняет... – Lex Hobbit Aug 13 '17 at 20:42