Быстрый способ возврата списка без определенного элемента в Python

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

suits = ["h", "c", "d", "s"] 

и я хочу вернуть список без 'c'

 noclubs = ["h", "d", "s"] 

есть ли простой способ сделать это?

  • Проблемы с разрешением при создании каталога с os.makedirs (python)
  • (Python) добавление списка в другой без скобок
  • нахождение max в python в соответствии с определенным пользовательским критерием
  • Абстрактные методы в Python
  • Элегантный формат для MAC-адреса в Python 3.2
  • Как определить класс в Python
  • PyCharm не распознает файлы Python
  • Приращение значения с плавающей запятой python на минимально возможную величину
  • 9 Solutions collect form web for “Быстрый способ возврата списка без определенного элемента в Python”

     >>> suits = ["h","c", "d", "s"] >>> noclubs = list(suits) >>> noclubs.remove("c") >>> noclubs ['h', 'd', 's'] 

    Если вам не нужны отдельные noclubs

     >>> suits = ["h","c", "d", "s"] >>> suits.remove("c") 
     suits = ["h","c", "d", "s"] noclubs = [x for x in suits if x != "c"] 

    На этот вопрос был дан ответ, но я хотел обратиться к комментарию о том, что использование понимания списка намного медленнее, чем использование .remove() .

    Некоторые профили с моей машины (с использованием Python 2.7.6).

     %%timeit x = ['a', 'b', 'c', 'd'] y = x[:] # fastest way to copy y.remove('c') 1000000 loops, best of 3: 405 ns per loop %%timeit x = ['a', 'b', 'c', 'd'] y = list(x) # not as fast copy y.remove('c') 1000000 loops, best of 3: 689 ns per loop %%timeit x = ['a', 'b', 'c', 'd'] y = [n for n in x if n != 'c'] # list comprehension 1000000 loops, best of 3: 544 ns per loop 

    Если вы используете самый быстрый способ скопировать список (который не очень читается), вы будете примерно на 36% быстрее, чем использование списка. Но если вы скопируете список, используя класс list() (который намного более распространен и Pythonic), то вы будете на 26% медленнее, чем использование списка.

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

    Большим преимуществом понимания списка в этом сценарии является то, что он намного более краткий (т. Е. Если у вас была функция, которая по какой-то причине удаляла элемент из данного списка, это можно было бы сделать в 1 строке, в то время как другой метод потребовал бы 3 строки.) Бывают моменты, когда однострочники могут быть очень удобными (хотя они обычно приходят за счет некоторой удобочитаемости). Кроме того, использование понимания списка превосходит в том случае, если вы действительно не знаете, действительно ли элемент, который нужно удалить, в самом начале списка. В то время как .remove() будет генерировать ValueError , понимание списка будет работать, как ожидалось.

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

     suits = ["h", "c", "d", "s"] noclubs = list(set(suits) - set(["c"])) # note no order guarantee, the following is the result here: # noclubs -> ['h', 's', 'd'] 

    Без использования для петель или лямбда-функций и сохранения порядка:

     suits = ["h","c", "d", "s"] noclubs = suits[:suits.index("c")]+suits[suits.index("c")+1:] 

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

    вы можете использовать фильтр (или ifilter from itertools)

     suits = ["h","c", "d", "s"] noclubs = filter(lambda i: i!='c', suits) 

    К сожалению, по-видимому, похоже, что это не встроено в Python.

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

    Реализация:

     def without(iterable, remove_indices): """ Returns an iterable for a collection or iterable, which returns all items except the specified indices. """ if not hasattr(remove_indices, '__iter__'): remove_indices = {remove_indices} else: remove_indices = set(remove_indices) for k, item in enumerate(iterable): if k in remove_indices: continue yield item 

    Применение:

     li = list(range(5)) without(li, 3) # <generator object without at 0x7f6343b7c150> list(without(li, (0, 2))) # [1, 3, 4] list(without(li, 3)) # [0, 1, 2, 4] 

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

    Если вы только хотите удалить один индекс, вы можете сделать его еще быстрее, используя k == remove_index вместо набора.

    Если важно удалить определенный элемент (в отличие от простой фильтрации), вам нужно что-то близкое к следующему:

     noclubs = [x for i, x in enumerate(suits) if i != suits.index('c')] 

    Вы также можете рассмотреть возможность использования set для более семантически правильного, если ваша проблема связана с игральными картами.

    Одна из возможностей – использовать filter :

     >>> import operator >>> import functools >>> suits = ["h", "c", "d", "s"] >>> # Python 3.x >>> list(filter(functools.partial(operator.ne, 'c'), suits)) ['h', 'd', 's'] >>> # Python 2.x >>> filter(functools.partial(operator.ne, 'c'), suits) ['h', 'd', 's'] 

    Вместо partial можно также использовать метод __ne__ 'c' здесь:

     >>> list(filter('c'.__ne__, suits)) ['h', 'd', 's'] 

    Тем не менее, последний подход не считается очень pythonic (обычно вам не следует использовать специальные методы – начиная с двойных подчеркиваний – напрямую), и он может дать странные результаты, если список содержит смешанные типы, но он может быть немного быстрее, чем partial подход ,

     suits = ["h", "c", "d", "s"]*200 # more elements for more stable timings %timeit list(filter('c'.__ne__, suits)) # 164 µs ± 5.98 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each) %timeit list(filter(functools.partial(operator.ne, 'c'), suits)) # 337 µs ± 13.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each) %timeit list(filter(lambda x: x != 'c', suits)) # 410 µs ± 13.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each) %timeit [x for x in suits if x != "c"] 181 µs ± 465 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each) 

    Python 3.5.2 протестирован с помощью команды miythons magic %timeit .

    Python - лучший язык программирования в мире.