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

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

то, Где точность текстового URL важна, при чтении вслух ее кому-то, в этом случае Вы не хотите путать подчеркивание для пространства (или наоборот).

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

6
задан SilentGhost 8 December 2009 в 12:35
поделиться

9 ответов

Для основных целей

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

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

. А если у вас много символов, кроме 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» , и отсылка к ответу гниблера: «Он сделал лучший».

6
ответ дан 8 December 2019 в 13:00
поделиться

Другой не самый быстрый способ, но я думаю, что он хорошо читается

>>> [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% медленнее

4
ответ дан 8 December 2019 в 13:00
поделиться
  1. фильтр (лямбда x: 'N' не в x или 'X' не в x, ваш_ список)
  2. your_list = [x для x в вашем_списке, если 'N' не в x или «X» не входит в x]
2
ответ дан 8 December 2019 в 13:00
поделиться

Any reason for duplicating the entire list? How about:

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

I know that list comprehensions are all the rage these days, but if the list is long we don't want to duplicate it without any reason right? You can take this to the next step and create a nice utility function:

>>> 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']
2
ответ дан 8 December 2019 в 13:00
поделиться

I like gnibbler’s memoization approach a lot. Either method using memoization should be identically fast in the big picture on large data sets, as the memo dictionary should quickly be filled and the actual test should be rarely performed. With this in mind, we should be able to improve the performance even more for large data sets. (This comes at some cost for very small ones, but who cares about those?) The following code only has to look up an item in the memo dict once when it is present, instead of twice (once to determine membership, another to extract the value).

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)

As I said, this should be noticeably faster when the genome is large (or at least not extremely small).

If you don’t want to duplicate the list, but just iterate over the filtered list, do something like:

for item in (item for item in codon if pred):
    do_something(item)
1
ответ дан 8 December 2019 в 13:00
поделиться

Существует также способ сделать это с помощью фильтра

    lst = filter(lambda x: 'X' not in x and 'N' not in x, list)
2
ответ дан 8 December 2019 в 13:00
поделиться

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

Лучше всего создать функцию фильтра и использовать 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)

Изменить:

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

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
1
ответ дан 8 December 2019 в 13:00
поделиться

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

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

Первоначально я думал, что ответ gnibbler может быть записан более быстрым и компактным способом с помощью 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)

Однако, как заметил gnibbler, значение в setdefault всегда оценивается (даже если , в общем,

0
ответ дан 8 December 2019 в 13:00
поделиться

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

def filter_genome(genome, killlist = set("X N".split()):
    return [codon for codon in genome if 0 == len(set(codon) | killlist)]
0
ответ дан 8 December 2019 в 13:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: