在python

时间:2016-01-05 10:53:07

标签: python list python-2.7

给出以下列表:

DNA_list = ['ATAT', 'GTGTACGT', 'AAAAGGTT']

我想过滤超过3个字符的字符串。我用以下代码实现了这个目标:

使用for循环:

long_dna = []
for element in DNA_list:
    length = len(element)
    if int(length) > 3:
        long_dna.append(element)
print long_dna

但是我希望我的代码更通用,所以我以后可以过滤任何长度的字符串,所以我使用了一个函数和for循环:

def get_long(dna_seq, threshold):
    return len(dna_seq) > threshold

long_dna_loop2 = []
for element in DNA_list:
    if get_long(element, 3) is True:
        long_dna_loop2.append(element)
print long_dna_loop2

我希望使用filter()实现相同的通用性,但我无法做到这一点。如果我使用上面的函数get_long(),当我将它与filter()一起使用时,我就无法将参数传递给它。这是不可能还是有办法绕过它?

我的代码filter()用于特定情况:

def is_long(dna):
        return len(dna) > 3

    long_dna_filter = filter(is_long, DNA_list)

8 个答案:

答案 0 :(得分:15)

使用lambda提供阈值,如下所示:

filter(lambda seq: get_long(seq, 3),
       dna_list)

答案 1 :(得分:15)

你要做的事情被称为partial function application:你有一个带有多个参数的函数(在这种情况下,2)并且希望得到一个从它派生的函数,并修复了一个或多个参数,你然后可以转到filter

某些语言(特别是功能性语言)具有此功能"内置"。在python中,您可以使用lambdas来执行此操作(正如其他人所示)或您可以使用functools library。特别是functools.partial

  

partial()用于部分函数应用程序,它“冻结”函数参数和/或关键字的某些部分,从而产生具有简化签名的新对象。例如,partial()可用于创建一个callable,其行为类似于int()函数,其中base参数默认为2:

>>> from functools import partial
>>> basetwo = partial(int, base=2)
>>> basetwo.__doc__ = 'Convert base 2 string to an int.'
>>> basetwo('10010')
18

所以你可以这样做:

filter(functools.partial(get_long, treshold=13), DNA_list)

答案 2 :(得分:10)

您需要使用filter()吗?为什么不使用更多的Pythonic列表理解?

示例:

>>> DNA_list = ['ATAT', 'GTGTACGT', 'AAAAGGTT']
>>> threshold = 3
>>> long_dna = [dna_seq for dna_seq in DNA_list if len(dna_seq) > threshold]
>>> long_dna
['ATAT', 'GTGTACGT', 'AAAAGGTT']

>>> threshold = 4
>>> [dna_seq for dna_seq in DNA_list if len(dna_seq) > threshold]
['GTGTACGT', 'AAAAGGTT']

这种方法的优点是可以将它转换为生成器,这可以根据您的应用提供改进的内存和执行,例如:如果你有很多DNA序列,并且你想迭代它们,那么将它们作为一个列表来实现会一次消耗大量的内存。等效生成器只需要用方括号[]替换方括号()

>>> long_dna = (dna_seq for dna_seq in DNA_list if len(dna_seq) > threshold)
<generator object <genexpr> at 0x7f50de229cd0>
>>> list(long_dna)
['GTGTACGT', 'AAAAGGTT']

在Python 2中,这种性能改进不是filter()的选项,因为它返回一个列表。在Python 3中filter()返回一个更类似于生成器的过滤器对象。

答案 3 :(得分:4)

你可以让is_long返回一个可以接受dna的函数,就像这样

>>> def is_long(length):
...     return lambda dna: len(dna) > length
... 

然后在filter中使用它,就像这样

>>> filter(is_long(3), DNA_list)
['ATAT', 'GTGTACGT', 'AAAAGGTT']
>>> filter(is_long(4), DNA_list)
['GTGTACGT', 'AAAAGGTT']

注意:请勿使用is运算符来比较布尔值或数字。而是尽可能地依赖数据的真实性。所以,在你的情况下,你可以编写你的第二个版本

if get_long(element, 3):
    long_dna_loop2.append(element)

引用programming recommendations in PEP-8

  

不要使用==。

将布尔值与True或False进行比较
 Yes:   if greeting:
 No:    if greeting == True:
 Worse: if greeting is True:

答案 4 :(得分:0)

以下是使用lambda的更多方法。第一个使用默认关键字参数来保持所需的长度。第二个只是在lambda正文中嵌入所需的长度。

#Create a list of strings
s = 'abcdefghi'
data = [s[:i+1] for i in range(len(s))]
print data

thresh = 3
print filter(lambda seq, n=thresh: len(seq) > n, data)

print filter(lambda seq: len(seq) > 5, data)

<强>输出

['a', 'ab', 'abc', 'abcd', 'abcde', 'abcdef', 'abcdefg', 'abcdefgh', 'abcdefghi']
['abcd', 'abcde', 'abcdef', 'abcdefg', 'abcdefgh', 'abcdefghi']
['abcdef', 'abcdefg', 'abcdefgh', 'abcdefghi']

在第一个例子中你也可以这样做:

print filter(lambda seq, n=3: len(seq) > n, data)

同样,在第二个示例中,您可以使用本地(或全局)变量替换文字5,例如:

thresh = 5
print filter(lambda seq: len(seq) > thresh, data)

答案 5 :(得分:0)

您总是可以创建一个callable,它返回一个适用于filter完成的比较的callable,如下例所示:

def main():
    dna_list = ['A', 'CA', 'TGATGATAC', 'GGGTAAAATC', 'TCG', 'AGGTCGCT', 'TT',
                'GGGTTGGA', 'C', 'TTGGAGGG']
    print('\n'.join(filter(length_at_least(3), dna_list)))


def length_at_least(value):
    return lambda item: len(item) >= value

# length_at_least = lambda value: lambda item: len(item) >= value

if __name__ == '__main__':
    main()

答案 6 :(得分:0)

你可以有更一般的案例。

由于函数是python中的一个对象,你可以创建另一个函数,它返回你想要的函数。

def f(threshhold):
    def g(x):
        return len(x)>threshhold
    return g #return a function

this_function = f(3)

DNA_list = ['ATAT', 'GTGTACGT', 'AAAAGGTT','AAA','AAAA']
filter(this_function, DNA_list)

output: ['ATAT', 'GTGTACGT', 'AAAAGGTT', 'AAAA']

g是你真正想要的,f是创造它的功能。

答案 7 :(得分:0)

我使用了如下内部函数和非本地范围的不同解决方案。由于我的代码不同,我已经修改了原始代码以供理解。

希望这会有所帮助。 :)

 def outerfun():
    charlimit = 3
    def is_long(dna):
        nonlocal charlimit
        return len(dna) > charlimit
    long_dna_filter = filter(is_long, DNA_list)     
    return long_dna_filter