[Python]创建一个for循环,想做一个字典

[Python]Creating a for loop, wanting to make a dictionary

我正在尝试通过 运行 通过 for 循环创建一个字典,其中包含对细菌的描述,关键是它的 DNA 序列。唯一的问题是我的变量不能存储多个数据集,它只会覆盖第一个数据集,因此我的字典只有一个输出。

#reads a fasta file and seperates the description and dna sequences
for line in resistance_read:
    if line.startswith(">"):
        description = line
    else: 
        sequence = line

#trying to get the output from the for loop and into the dictionary
bacteria_dict = {description:sequence}

输出:

line3description
dna3sequence

但是,使用下面的代码,我可以获得所有输出

for line in resistance_read:
    if line.startswith(">"):
       print line
    else: 
       print line

输出:

line1description
line2description
line3description
dna1sequence
dna2sequence
dna3sequence

您不断地在迭代中覆盖变量的值。 sequencedescription 仅在迭代完成时保留最后的值。

相反,先创建字典 并添加到其中,作为更复杂的数据结构,它可以容纳更多数据。


但是,有一个更简单的方法...

首先您需要打开文件并阅读其中的行。为此,您可以使用 with context manager:

with open('file_path', 'r') as f:
    # used strip() to remove '\n'
    lines = [line.strip() for line in f]

现在所有的行都在一个名为 lines 的列表中,您想要在描述和序列之间创建一个映射。

如果描述行刚好在序列行上方,请使用此 slicing:

# take every other line (intervals of 2) starting from index 0
descriptions = lines[0::2]
sequences = lines[0::2]

现在使用 zip 将它们压缩在一起并从每对创建一个映射:

result = dict(zip(descriptions, sequences))

如果是相反的方式,您可以使用正好相反的方法:

result = dict(zip(lines[1::2], lines[0::2]))

编辑:

根据你的更新,假设每个序列都有一个描述(确切地说),似乎是将行列表分成两半,然后压缩:

middle = len(lines) / 2
result = dict(zip(lines[:mid], lines[mid:]))

根据您向我们展示的示例,您的文件格式似乎是 N 行描述后跟 N 行 DNA 序列。这个答案假设每个描述或 DNA 序列都是一行,并且有多少描述就有多少序列。

如果您可以轻松地将所有内容放入内存中,那么我能想到的最简单的方法就是按照上面 Reut Sharabani 的建议开始:

with open('file_path', 'r') as f:
    # used strip() to remove '\n'
    lines = [line.strip() for line in f]

一旦有了 lines,就可以很容易地创建两个列表,将它们压缩,然后创建一个 dict:

descriptions = [line for line in lines if line.startswith('>')]
sequences = [line for line in lines if not line.startswith('>')]
result = dict(zip(sequences, descriptions))

但是,如果文件非常大,并且您不想执行相当于读取其整个长度四次的操作,您可以通过存储描述并将它们与序列匹配来只处理一次随着序列的出现。

result = {}
descriptions = []
with open('file_path', 'r') as f:

    line = f.readline().strip()

    while line.startswith('>'):
        descriptions.append(line)
        line = f.readline().strip()

    result[line] = descriptions.pop(0)
    for line in f:
        result[line] = descriptions.pop(0)

当然这会遇到麻烦,如果:

  • 序列数量与描述不完全相同
  • 序列与描述的顺序不同
  • 序列和描述不在整体块中。