根据同一lis中的下一个项目从列表中删除项目

2024-09-28 01:34:02 发布

您现在位置:Python中文网/ 问答频道 /正文

我刚开始学习python,这里有一个蛋白质序列的分类列表(共59000个序列),其中一些是重叠的。我在这里列出了一个玩具清单,例如:

ABCDE
ABCDEFG
ABCDEFGH
ABCDEFGHIJKLMNO
CEST
DBTSFDE
DBTSFDEO
EOEUDNBNUW
EOEUDNBNUWD
EAEUDNBNUW
FEOEUDNBNUW
FG
FGH

我想去掉那些较短的重叠,只保留最长的一个,这样期望的输出如下所示:

^{pr2}$

我该怎么做?我的代码如下:

with open('toy.txt' ,'r') as f:
    pattern = f.read().splitlines()
    print pattern

    for i in range(0, len(pattern)):
        if pattern[i] in pattern[i+1]:
            pattern.remove(pattern[i])
        print pattern

我收到了错误信息:

['ABCDE', 'ABCDEFG', 'ABCDEFGH', 'ABCDEFGHIJKLMNO', 'CEST', 'DBTSFDE', 'DBTSFDEO', 'EOEUDNBNUW', 'EAEUDNBNUW', 'FG', 'FGH']
['ABCDEFG', 'ABCDEFGH', 'ABCDEFGHIJKLMNO', 'CEST', 'DBTSFDE', 'DBTSFDEO', 'EOEUDNBNUW', 'EAEUDNBNUW', 'FG', 'FGH']
['ABCDEFG', 'ABCDEFGHIJKLMNO', 'CEST', 'DBTSFDE', 'DBTSFDEO', 'EOEUDNBNUW', 'EAEUDNBNUW', 'FG', 'FGH']
['ABCDEFG', 'ABCDEFGHIJKLMNO', 'CEST', 'DBTSFDE', 'DBTSFDEO', 'EOEUDNBNUW', 'EAEUDNBNUW', 'FG', 'FGH']
['ABCDEFG', 'ABCDEFGHIJKLMNO', 'CEST', 'DBTSFDEO', 'EOEUDNBNUW', 'EAEUDNBNUW', 'FG', 'FGH']
['ABCDEFG', 'ABCDEFGHIJKLMNO', 'CEST', 'DBTSFDEO', 'EOEUDNBNUW', 'EAEUDNBNUW', 'FG', 'FGH']
['ABCDEFG', 'ABCDEFGHIJKLMNO', 'CEST', 'DBTSFDEO', 'EOEUDNBNUW', 'EAEUDNBNUW', 'FG', 'FGH']
['ABCDEFG', 'ABCDEFGHIJKLMNO', 'CEST', 'DBTSFDEO', 'EOEUDNBNUW', 'EAEUDNBNUW', 'FGH']
Traceback (most recent call last):
  File "test.py", line 8, in <module>
    if pattern[i] in pattern[i+1]:
IndexError: list index out of range

Tags: in序列patternprintfgcestabcdeabcdefg
3条回答

您可以使用^{}max()来帮助您:

from itertools import groupby

with open('toy.txt') as f_input:
    for key, group in groupby(f_input, lambda x: x[:2]):
        print(max(group, key=lambda x: len(x)).strip())

这将显示:

^{pr2}$

groupby()的工作原理是基于函数返回匹配项的列表,在本例中是具有相同前2个字符的连续行。然后,max()函数接受此列表并返回长度最长的列表项。在

还有其他可行的答案,但没有一个能解释你的实际问题。你实际上已经接近一个有效的解决方案,在我看来,什么是最可读的答案。在

错误来自这样一个事实,即在使用range()检查索引时,对同一个列表进行了变异。

因此,在增加i变量时,您正在从列表中删除项,这在某一点上不可避免地导致index error。在

因此,这里是您的初始代码的一个工作版本

pattern = ["ABCDE","ABCDEFG","ABCDEFGH","ABCDEFGHIJKLMNO","CEST","DBTSFDE","DBTSFDEO","EOEUDNBNUW","EAEUDNBNUW","FG","FGH"]
output_pattern = []


for i in range(0, (len(pattern)-1)):
    if not pattern[i] in pattern[i+1]:
        output_pattern.append(pattern[i]) 

# Adding the last item
output_pattern.append(pattern[-1])   
print (output_pattern)

>>>> ['ABCDEFGHIJKLMNO', 'CEST', 'DBTSFDEO', 'EOEUDNBNUW', 'EAEUDNBNUW', 'FGH']    

请注意,如果您的列表是按照您在注释部分中提到的那样进行排序的,则此代码将有效。在

这段代码在做什么?

基本上,它使用与初始答案相同的逻辑,在这个逻辑中迭代列表并检查下一项是否包含当前项。但是,使用另一个列表并迭代到before last项,可以解决索引问题。但现在有个问题

最后一项该怎么办?

由于列表是排序的,您可以认为最后一项始终是唯一的。这就是为什么我用

^{pr2}$

添加初始列表的最后一项。在

重要提示

这个答案是针对OP最初的问题写的,他想保持较长的重叠,我根据同一列表中的下一项引用。正如@Chris_Rands所说,如果你的担忧与生物任务有关,并且需要找到任何重叠,那么这个解决方案不适合你的需要。在

此代码无法识别潜在重叠的示例

pattern = ["ACD", "AD", "BACD"]

它将输出相同的结果而不删除可能的"ACD"重叠。现在,就像澄清一样,这意味着一个更复杂的算法,我最初认为这超出了问题的要求范围。如果这是你的情况,我可能完全错了,但是我真的认为C++实现似乎更合适。看看@Chris_Rands在评论部分建议的CD-Hit算法。在

# assuming list is sorted:
pattern = ["ABCDE",
"ABCDEFG",
"ABCDEFGH",
"ABCDEFGHIJKLMNO",
"CEST",
"DBTSFDE",
"DBTSFDEO",
"EOEUDNBNUW",
"EAEUDNBNUW",
"FG",
"FGH"]

pattern = list(reversed(pattern))

def iterate_patterns():
    while pattern:
        i = pattern.pop()
        throw_it_away = False
        for p in pattern:
            if p.startswith(i):
                throw_it_away = True
                break
        if throw_it_away == False:
            yield i

print(list(iterate_patterns()))

输出:

['ABCDEFGHIJKLMNO', 'CEST', 'DBTSFDEO', 'EOEUDNBNUW', 'EAEUDNBNUW', 'FGH']

相关问题 更多 >

    热门问题