【问题标题】:How do I fix this list index out of range error?如何修复此列表索引超出范围错误?
【发布时间】:2021-03-12 10:43:55
【问题描述】:

我正在尝试通过一个 txt 文件提取某些数字,将它们存储在一个列表中,然后使用这些数字提取存储在同一文件中的字符串。我的代码适用于我的一些文件,但突然出现列表索引超出范围错误。

这是我试图退出的文本文件部分的示例

                     /note="tRNA-Arg2"
     tRNA            5573494..5573567
                     /locus_tag="Tery_R0035"
                     /product="tRNA-Arg"

     tRNA            complement(5630800..5630872)
                     /locus_tag="Tery_R0036"
                     /product="tRNA-His"

我正在尝试获取写在 tRNA 之后的数字。

这是我将数字提取到列表中的代码:

def extract_numbers(line):
    #empty list
    numbers = []
    #creates a buffer (temporary space)
    digits = ""
    #for character in the line
    for c in line:
        #if its a digit
        if c.isdigit():
            #add character to the buffer
            digits += c
        #if it isnt a number
        else:
            #if there is something in the buffer (ie its not 0)
            if len(digits) > 0:
                #add the buffer to the numbers list
                numbers.append(digits)
                #empty again
                digits = ""
    #to make sure the last number is added to the list
    if len(digits) > 0:
        numbers.append(digits)
    return numbers

并使用最后一个函数将其写入文件本身

def extract_tRNA(path):
    with io.open(path, mode="r", encoding="utf-8") as file:
        genome = file.readlines()
        start_stop = []
        for line in genome:
            if "tRNA" in line[0:21]:
                numbers = extract_numbers(line[21:])
                start_stop.append((int(numbers[0]), int(numbers[1])))
        return start_stop

然后,我用这个运行它:

work_dir = "/Users/..."
for path in glob.glob(os.path.join(work_dir, "*.gbff")):

    sequences = extract_seq(path)
    tRNA_loc = extract_tRNA(path)
    extract_genes(path, tRNA_loc, sequences)
    print(path)

是我的文件还是代码?我也不确定是否有更简单的方法来做同样的事情?

感谢您的帮助!

更新尝试正则表达式:

work_dir = "where my files are"
for path in glob.glob(os.path.join(work_dir, "*.gbff")):
    with io.open(path, mode="r", encoding="utf-8") as file:
        genome = file.readlines()
        for line in genome:
            if "tRNA" in line[0:21]:
                p = re.compile('\d+')  # \d means digit and + means one or more
                m = p.findall(line)
        print(m)

【问题讨论】:

  • 对于您的第一个号码,字符串为5573494..5573567。您是否希望 tRNA 是一个大数字 55734945573567 或数字列表 [5573494, 5573567]' ? Or did you want long strings: "55734945573567"` 或字符串列表 `["5573494", "5573567"]' 可能有一种更简单的方法,具体取决于你想要什么。
  • 数字总是以同样的方式分开吗?有两个点:..?总是有两个数字吗?
  • @rajah9 是的,总是有 2 个点和数字。我希望将两个数字分开在一个列表中,这就是我现在得到的!但不确定为什么它不起作用。我知道正则表达式可能更容易,但是当我尝试时我无法弄清楚模式
  • 您需要缩进print(m),使其位于m = p.findall(line)下方。

标签: python list range


【解决方案1】:

我假设您想要从您的函数 extract_numbers 返回的字符串列表。

Python 使用称为正则表达式 (documentation) 的强大功能。

这是一个提取所有一位或多位数字的字符串的示例。

import re

line = "     tRNA            5573494..5573567"
p = re.compile('\d+') # \d means digit and + means one or more
m = p.findall(line)
m # returns ['5573494', '5573567']

【讨论】:

  • 是的,我首先尝试使用正则表达式,但我无法弄清楚模式,因为文件中的众多 tRNA 标记有时前面有补码,有时没有。一个文件中通常也有大约 40-50 个 tRNA 标签
  • 模式\d+ 将起作用(并且不在乎有多少点或前面有多少个字符)。它将数字字符串作为单独的数字序列返回。您可以在这里看到它的实际效果并尝试不同的字符串:pythex.org/…
  • 哦,谢谢!我已经为我的问题添加了更新,但它不起作用?它正在拉出一个事件:也许我需要将它们放在一个列表中?
  • 请更具体。它产生什么? (“但它不起作用”没有帮助;它迫使我重新做你的整个程序。)
  • 啊,你的解决方案解决了!
【解决方案2】:

根据您对要实现的目标的描述,这应该可行。请注意,file.txt 是您在上面包含的示例:

import re

with open("file.txt") as f:
    data =f.readlines()
    
    numberList = []
    
    for line in data:
        dataList = line.split() #words separated by spaces split into list
        try: #if tRNA is not in line
            numberIndex = dataList.index("tRNA") + 1 # the numbers that are written after tRNA
            numberList.append(dataList[numberIndex])
        except Exception as _:
            continue

#The above cleans you data from all other numbers i.e "Tery_R0035"

#Taken from top answer (@rajah9)
p = re.compile('\d+') # \d means digit and + means one or more
for numData in numberList:
    m = p.findall(numData)
    print(m)

【讨论】:

  • 这可行!我遇到的问题是每个文件中都有大量的 tRNA,我需要找到这些 tRNA,然后将其取出
  • @Meems 我已经编辑了我的答案以处理多个“tRNA”实例
  • 谢谢!这部分有效,我遇到的问题是它排除了所有出现的 tRNA,但我只需要行首的那些!输出如下所示:complement(42730..42801) complement(68921..68995) Synthetase" 158662..158734 158744..158826 complement(202341..202414) complement(202420..202492) etc etc
  • 我再次编辑了我的解决方案以包含 reg exp(从@rajah9 复制),接受的解决方案如何处理诸如 Tery_R0036 之类的数字?
  • 为了提高效率,我会将 re.compile 步骤移到 for 循环之前。 (不需要为每一行重新编译;这只需要发生一次。)
猜你喜欢
  • 1970-01-01
  • 2021-05-30
  • 2019-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多