选择文件中的特定列表

时间:2015-07-13 23:57:14

标签: python

我一直在使用Python字典用COG / NOG标识符替换md5值。这就是我到目前为止所做的......

#!/usr/bin/python

import sys

fil = sys.argv[1]

# load md5 -> COG into dictionary

with open(fil) as fin: 
    rows = ( line.strip().split('\t') for line in fin )
    d = { row[0]:row[1] for row in rows }

# open blast output, replace md5 with COG by looking up md5 in the dictionary

    blasted = open(sys.argv[2])
    for line in blasted:
            linearr = line.split()
            if linearr[2] > '90.00':
                    line.split()
                    needed = linearr[0:2]
                    md5 = linearr[1]                                
                    ret = []
                    for md5 in needed:
                            ret.append(d.get(md5,md5))
                            "".join(ret)
                            print ret

这使我得到了这个输出,各种大小和内容的列表......

['fig|357276.26.peg.4486']
['fig|357276.26.peg.4486', 'f3e68ef307f962ba6b836a94ff0e2216']
['fig|357276.26.peg.4486']
['fig|357276.26.peg.4486', 'COG0860']
['fig|357276.26.peg.4486']
['fig|357276.26.peg.4486', '05e94199eef6fbaf225618f9deaf847c']

因此需要抛出单个项目列表以及保留md5值的列表。我需要的是只选择具有COG / NOG第二个元素的列表,如上面的第4个列表。

我无法选择列表的第二项来过滤这些结果,因为并非所有列表都有第二项。任何人都可以为此建议一种方法吗?

更新: 我只能用一个项目删除列表。现在我的列表看起来像这样......

['fig|357276.26.peg.4485', 'NOG73961']
['fig|357276.26.peg.4485', '19c060b530e8fa9598de068387bc3225']
['fig|357276.26.peg.4486', '8daa25fe83eb1a204c51861cb77945f5']
['fig|357276.26.peg.4486', '5c253078a0a6c51eca320dfd92991a70']
['fig|357276.26.peg.4486', '8707bd7fa7489ff69233ce735c1c6cbf']
['fig|357276.26.peg.4486', 'f3e68ef307f962ba6b836a94ff0e2216']
['fig|357276.26.peg.4486', 'COG0860']
['fig|357276.26.peg.4486', '05e94199eef6fbaf225618f9deaf847c']

现在我只需要选择包含以NOG或COG开头的第二项的列表......任何建议?

3 个答案:

答案 0 :(得分:1)

假设您有一个列表,例如values = [ [1], [1,2], [3,4] ]

首先,使用filter功能删除所有项目:

values1 = filter(lambda x: len(x) > 1, values)

现在您需要根据COG / NOG进行过滤。由于现在只有2个元素的列表,我们可以直接选择第二个元素:

filter(lambda x: "NOG" in x[1] of "COG" in x[1], values1)

为了减少整个事情,我们可以合并两者:

def check_cog_nog(x):
    if len(x) > 1:
        y = x[1].lower()
        if "nog" in y or "cog" in y:
            return True
    return False

filter(check_cog_nog, values)

答案 1 :(得分:0)

在尝试访问第二个元素之前,只需使用len()检查列表是否足够长。

[编辑:就像上面的第一条评论一样,在我开始这个答案后发布了。 (我没有足够的声誉来评论自己。)]

[编辑2:这里有一些关于你的代码的注释。除非您确定数据来源,否则您可能需要考虑进行一些检查,以确保每一行都符合您的需要。]

blasted = open(sys.argv[2])
for line in blasted:
        linearr = line.split()
        if linearr[2] > '90.00':  # <-- this will blow up if not enough elements
                line.split()      # <--- this doesn't do anything
                needed = linearr[0:2]  # <- this could get 0-3 elements
                md5 = linearr[1]  # <-- This will blow up if not enough elements
                ret = []
                for md5 in needed:
                        ret.append(d.get(md5,md5))
                        "".join(ret)
                        print ret

答案 2 :(得分:0)

如果您的列表存储在variable ret中,那么您可以使用此列表理解来实现您的需求:

new_ret = [i for i in ret if len(i) > 1 and (i[1].startswith('COG') or i[1].startswith('NOG'))]
print (new_ret)

输出:

[['fig|357276.26.peg.4486', 'COG0860']]

如果ret包含i[1]NOD开头的元素,new_ret也会包含这些元素。