Удаление элемента из списка на основе предиката

Я хочу удалить элемент из списка, чтобы элемент содержал 'X' или 'N' . Я должен подать заявку на большой геном. Вот пример:

вход:

 codon=['AAT','XAC','ANT','TTA'] 

ожидаемый результат:

 codon=['AAT','TTA'] 

9 Solutions collect form web for “Удаление элемента из списка на основе предиката”

Для базовых целей

 >>> [x for x in ['AAT','XAC','ANT','TTA'] if "X" not in x and "N" not in x] ['AAT', 'TTA'] 

Но если у вас огромный объем данных, я предлагаю вам использовать dict или set

И если у вас много символов, кроме X и N, вы можете сделать это

 >>> [x for x in ['AAT','XAC','ANT','TTA'] if not any(ch for ch in list(x) if ch in ["X","N","Y","Z","K","J"])] ['AAT', 'TTA'] 

ПРИМЕЧАНИЕ: list(x) может быть просто x , а ["X","N","Y","Z","K","J"] может быть просто "XNYZKJ" , и обратитесь к gnibbler answer, He сделал лучший.

Еще один не быстрый способ, но я думаю, что он прекрасно читает

 >>> [x for x in ['AAT','XAC','ANT','TTA'] if not any(y in x for y in "XN")] ['AAT', 'TTA'] >>> [x for x in ['AAT','XAC','ANT','TTA'] if not set("XN")&set(x)] ['AAT', 'TTA'] 

Этот путь будет быстрее для длинных кодонов (при условии, что есть некоторое повторение)

 codon = ['AAT','XAC','ANT','TTA'] def pred(s,memo={}): if s not in memo: memo[s]=not any(y in s for y in "XN") return memo[s] print filter(pred,codon) 

Вот метод, предложенный Джеймсом Бруком, вам нужно будет проверить, что быстрее для ваших данных

 codon = ['AAT','XAC','ANT','TTA'] def pred(s,memo={}): if s not in memo: memo[s]= not set("XN")&set(s) return memo[s] print filter(pred,codon) 

Для этого образцового кодона версия с использованием наборов примерно на 10% медленнее

Существует также метод его использования с использованием фильтра

  list = filter(lambda x: 'X' not in x and 'N' not in x, list) 
  1. filter(lambda x: 'N' not in x or 'X' not in x, your_list)
  2. your_list = [x for x in your_list if 'N' not in x or 'X' not in x]

Мне очень нравится подход memoization гнибблера. Любой метод, использующий memoization, должен быть точный в большой картине на больших наборах данных, так как словарь заметок должен быть быстро заполнен и фактический тест должен быть редко выполнен. Имея это в виду, мы должны быть в состоянии улучшить производительность еще больше для больших наборов данных. (Это происходит по какой-то цене для очень маленьких, но кому это нужно?) Следующий код должен искать элемент в памятке только один раз, когда он присутствует, а не дважды (один раз для определения членства, другой для извлечения Значение).

 codon = ['AAT', 'XAC', 'ANT', 'TTA'] def pred(s,memo={}): try: return memo[s] except KeyError: memo[s] = not any(y in s for y in "XN") return memo[s] filtered = filter(pred, codon) 

Как я уже сказал, это должно быть заметно быстрее, когда геном большой (или, по крайней мере, не очень маленький).

Если вы не хотите дублировать список, а просто перебираете фильтрованный список, сделайте что-то вроде:

 for item in (item for item in codon if pred): do_something(item) 

Если вы имеете дело с чрезвычайно большими списками, вы хотите использовать методы, которые не включают в себя перемещение всего списка, больше, чем вам абсолютно необходимо.

Лучше всего создать функцию фильтрации и использовать itertools.ifilter , например:

 new_seq = itertools.ifilter(lambda x: 'X' in x or 'N' in x, seq) 

Это фактически проверяет каждый элемент в списке, пока вы на самом деле не перейдете к нему. Обратите внимание, что вы можете фильтровать отфильтрованную последовательность так же, как и исходную последовательность:

 new_seq1 = itertools.ifilter(some_other_predicate, new_seq) 

Редактировать:

Кроме того, небольшое тестирование показывает, что memoizing найденных записей в наборе, вероятно, обеспечит достаточное улучшение, которое стоит сделать, а использование регулярного выражения, вероятно, не способ:

 seq = ['AAT','XAC','ANT','TTA'] >>> p = re.compile('[X|N]') >>> timeit.timeit('[x for x in seq if not p.search(x)]', 'from __main__ import p, seq') 3.4722548536196314 >>> timeit.timeit('[x for x in seq if "X" not in x and "N" not in x]', 'from __main__ import seq') 1.0560532134670666 >>> s = set(('XAC', 'ANT')) >>> timeit.timeit('[x for x in seq if x not in s]', 'from __main__ import s, seq') 0.87923730529996647 

Как запросил С.Марк, это моя версия. Это, вероятно, медленнее, но облегчает изменение того, что удаляется.

 def filter_genome(genome, killlist = set("XN".split()): return [codon for codon in genome if 0 == len(set(codon) | killlist)] 

Любая причина для дублирования всего списка? Как насчет:

 >>> def pred(item, haystack="XN"): ... return any(needle in item for needle in haystack) ... >>> lst = ['AAT', 'XAC', 'ANT', 'TTA'] >>> idx = 0 >>> while idx < len(lst): ... if pred(lst[idx]): ... del lst[idx] ... else: ... idx = idx + 1 ... >>> lst ['AAT', 'TTA'] 

Я знаю, что в наши дни все понимают суть списка, но если список длинный, мы не хотим дублировать его без каких-либо оснований? Вы можете перейти к следующему шагу и создать приятную функцию утилиты:

 >>> def remove_if(coll, predicate): ... idx = len(coll) - 1 ... while idx >= 0: ... if predicate(coll[idx]): ... del coll[idx] ... idx = idx - 1 ... return coll ... >>> lst = ['AAT', 'XAC', 'ANT', 'TTA'] >>> remove_if(lst, pred) ['AAT', 'TTA'] >>> lst ['AAT', 'TTA'] 

Это (асимптотически) быстрее использовать регулярное выражение, чем поиск много раз в одной строке для определенного символа: на самом деле, с регулярным выражением, последовательности читаются не более одного раза (вместо двух, когда буквы не найдены , в оригинальном ответе гниблера, например). С мнимаяю гнибблера подход к регулярному выражению гласит:

 import re remove = re.compile('[XN]').search codon = ['AAT','XAC','ANT','TTA'] def pred(s,memo={}): if s not in memo: memo[s]= not remove(s) return memo[s] print filter(pred,codon) 

Это должно быть (асимптотически) быстрее, чем с помощью проверок «in s» или «set» (т. Е. Вышеприведенный код должен быть быстрее для достаточно длинных строк s ).

Первоначально я думал, что ответ гниблера может быть написан быстрее и более компактно с dict.setdefault ():

 codon = ['AAT','XAC','ANT','TTA'] def pred(s,memo={}): return memo.setdefault(s, not any(y in s for y in "XN")) print filter(pred,codon) 

Однако, как заметил гниблер, значение в setdefault всегда оценивается (хотя, в принципе, его можно оценить только тогда, когда ключ словаря не найден).

  • Ввод каталогов в виде строк в python
  • Как преобразовать числовые диапазоны строк в список в Python
  • Извлечение определенных символов из строки
  • Python Удалить суммарную сумму в долларах
  • Python Regex - проверка заглавной буквы в нижнем регистре после
  • Использование первой строки как переменной с python
  • Python запускает специальные символы в sys argv
  • Удаление ненужных символов из строки в Python
  •  
    Interesting Posts for Van-Lav

    Что означает «для x в y или z:» в Python?

    Явная утечка памяти с numpy tolist () в длительном процессе

    Python numpy.nan и логические функции: неправильные результаты

    Возникли проблемы при использовании scipy.integrate.odeint с python

    nltk NaiveBayesClassifier для анализа настроений в блогах

    В Pandas, что означает эквивалент «nrows» от read_csv (), который будет использоваться в read_excel ()?

    Использование собственных объектов модуля в __main__.py

    Python: Как я могу определить в sphinx, какие файлы .rst и каталоги должны использоваться?

    TypeError: строковые индексы должны быть целыми, а не str на Python Dictionary

    Использует ли Python фрагмент по ссылке на строки?

    Minimax объяснил для идиота

    Непрерывный график времени с датами по оси x

    Unicode в PowerShell с Python? Альтернативные оболочки в Windows?

    Конфигурация Aptana: сконфигурированный интерпретатор не существует в файловой системе

    Поддерживает ли iPython встроенную поддержку просмотра переменной в пейджере?

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