在较大的lis中处理可变大小的子列表

2024-04-27 14:24:28 发布

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

我是一名生物工程博士生,想自学Python编程,以使我研究的一部分自动化,但我遇到了一个在更大的列表中处理子列表的问题,我似乎无法解决。在

基本上,我要做的是写一个小脚本,它将处理一个CSV文件,其中包含我正在使用各种DNA组装方法构建的质粒序列列表,然后输出构建质粒所需的引物序列。在

下面是我要处理的场景:

当我想构建一个质粒时,我必须在Excel电子表格中输入该质粒的完整序列。我必须在两种DNA组装方法中选择一种,叫做“吉布森”和“iPCR”。每个“iPCR”程序集只需要列表中的一行,所以我已经知道如何处理这些人了,因为我只需将我正在构建的质粒的完整序列放入一个细胞。”另一方面,Gibson的“程序集”要求我必须将整个DNA序列分成更小的块,因此有时我需要Excel电子表格中的2-5行来完整地描述一个质粒。在

最后我得到了一个电子表格,结果是这样的:

构建…..策略…..名称

1…..Gibson…..p(OmpC)-cI::p(cI)-LacZ控制器
1…..Gibson…..P(OmpC)-cI::P(cI)-LacZ控制器
1…..Gibson…..P(OmpC)-cI::P(cI)-LacZ控制器
2…..iPCR…….P(cpcG2)-K1F控制器,带K1F位置反馈
3…..Gibson…..P(cpcG2)-K1F控制器,启动子位置互换
3…..Gibson…..P(cpcG2)-K1F控制器,启动子位置互换
4…..iPCR…….P(cpcG2)-K1F控制器,具有更强的K1F RBS库

我认为这样长的名单很有代表性。在

所以我遇到的问题是,我希望能够遍历列表并处理gibson,但是我似乎无法让代码按照我想要的方式工作。以下是我目前编写的代码:

#import BioPython Tools
from Bio.Seq import Seq
from Bio.Alphabet import IUPAC

#import csv tools
import csv
import sys
import os

with open('constructs-to-make.csv', 'rU') as constructs:
    construct_list = csv.reader(constructs, delimiter=',')
    construct_list.next()
    construct_number = 1
    primer_list = []
    temp_list = []
    counter = 2

    for row in construct_list:
        print('Current row is row number ' + str(counter))
        print('Current construct number is ' + str(construct_number))
        print('Current assembly type is ' + row[1])
        if row[1] == "Gibson": #here, we process the Gibson assemblies first
            print('Current construct number is: #' + row[0] + ' on row ' + str(counter) + ', which is a Gibson assembly')
##            print(int(row[0]))
##            print(row[3])
            if int(row[0]) == construct_number:
                print('Adding DNA sequence from row ' + str(counter) + ' for construct number ' + row[0])
                temp_list.append(str(row[3]))
                counter += 1
            if int(row[0]) > construct_number:
                print('Current construct number is ' + str(row[0]) + ', which is greater than the current construct number, ' + str(construct_number))
                print('Therefore, going to work on construct number ' + str(construct_number))
                for part in temp_list: #process the primer design work here
                    print('test')
##                    print(part)
                construct_number += 1
                temp_list = []
                print('Adding DNA from row #' + str(counter) + ' from construct number ' + str(construct_number))
                temp_list.append(row)
                print('Next construct number is number ' + str(construct_number))
                counter += 1
##            counter += 1
        if str(row[1]) == "iPCR":
            print('Current construct number is: ' + row[0] + ' on row ' + str(counter) + ', which is an iPCR assembly.')
            #process the primer design work here
            #get first 60 nucleotides from the sequence
            sequence = row[3]
            fw_primer = sequence[1:61]
            print('Sequence of forward primer:')
            print(fw_primer)
            last_sixty = sequence[-60:]
##            print(last_sixty)
            re_primer = Seq(last_sixty).reverse_complement()
            print('Sequence of reverse primer:')
            print(re_primer)
            #ending code: add 1 to counter and construct number
            counter += 1
            construct_number += 1
##            if int(row[0]) == construct_number:
##        else:
##            counter += 1
##            construct_number += 1
##    print(temp_list)

##        for row in temp_list:
##    print(temp_list)        
##    print(temp_list[-1])
#                fw_primer = temp_list[counter - 1].

(我知道这段代码看起来很糟糕——除了介绍性Java之外,我从来没有学过任何编程类。)

这个代码的问题是,如果我有n个“构造体”(又称质粒),我正试图通过“Gibson”程序集构建,它将处理第一个n-1个质粒,而不是最后一个。不过,我想不出有什么更好的方法来编写这段代码,但是我可以看到,对于我正在尝试实现的工作流,知道如何处理列表中的“n”个事物,但是对于行数可变的每一个“事物”,对我来说会非常有用。在

我真的很感谢大家的帮助!谢谢!在


Tags: importnumber列表iscounter控制器constructtemp
2条回答

The problem with this code is that if I have n "constructs" (a.k.a. plasmids) that I'm trying to build by "Gibson" assembly, it will process the first n-1 plasmids, but not the last one.

这实际上是一个普遍的问题,最简单的解决方法是在循环之后添加一个检查,如下所示:

for row in construct_list:
    do all your existing code
if we have a current Gibson list:
    repeat the code to process it.

当然,你不想重复你自己…所以你把工作转移到一个函数中,你在两个地方都调用这个函数。在

不过,我可能会用不同的方式来写这个,使用^{}。我知道乍一看这可能看起来“太先进了”,但值得一试,看看你是否能理解它,因为它使事情简单得多。在

^{pr2}$

现在,您将把每个构造作为一个单独的列表,因此根本不需要temp_list。例如,第一组将是:

[[1, 'Gibson', 'P(OmpC)-cI::P(cI)-LacZ controller'],
 [1, 'Gibson', 'P(OmpC)-cI::P(cI)-LacZ controller'],
 [1, 'Gibson', 'P(OmpC)-cI::P(cI)-LacZ controller']]

接下来是:

[[2, 'iPCR', 'P(cpcG2)-K1F controller with K1F pos. feedback']]

最后也不会有剩下的人担心了。在

所以:

for group in itertools.groupby(construct_list, key=get_strategy):
    construct_strategy = get_strategy(group[0])
    if construct_strategy == "Gibson":
        # your existing code, using group instead of temp_list,
        # and no need to maintain temp_list at all
    elif construct_strategy == 'iPCR":
        # your existing code, using group[0] instead of row

一旦你克服了抽象障碍,用这种方式来思考问题就简单多了。在

事实上,一旦你开始直观地掌握迭代器,你就会发现itertools(以及它的docs页面上的菜谱,第三方库more_itertools,以及你可以自己编写的类似代码)把很多复杂的问题变成了非常简单的问题。“如何跟踪行列表中的当前匹配行组?”是“保留一个临时列表,记住每次组更改时都要检查它,然后在结尾处再次检查是否有剩余项”,但它的答案是“如何将行迭代转换为行组迭代?”是“在groupby中包装迭代器。”

您可能还想添加一个assert或其他检查all(row[1] == construct_strategy for row in group[1:]),在iPCR的情况下,len(group) == 1,没有意外的第三个策略,等等,所以当您不可避免地遇到错误时,可以更容易地判断它是坏数据还是坏代码。在

同时,与其使用csv.reader,跳过第一行,用无意义的数字来引用列,不如使用^{}

with open('constructs-to-make.csv', 'rU') as constructs:
    primer_list = []
    def get_strategy(row):
        return row["Strategy"]
    for group in itertools.groupby(csv.DictReader(constructs), key=get_strategy):
        # same as before, but with
        # ... row["Construct"] instead of row[0]
        # ... row["Strategy"] instead of row[1]
        # ... row["Name"] instead of row[2]

只是一些关于python的通用编码帮助。如果你还没读过PEP8,就读吧。在

为了保持清晰的代码,可以将变量分配给记录/行中引用的字段。在

对于引用的任何字段,我将添加如下内容:

construct_idx = 0

另外,我建议使用字符串格式,这样更干净。在

所以:

^{pr2}$

而不是:

print('Current construct number is: #' + row[0] + ' on row ' + str(counter) + ', which is a Gibson assembly')

如果您正在创建一个csv reader对象,那么将它的变量名“*\u list”设置为可能缺少前导。称之为“*\u reader”更直观。在

construct_reader = csv.reader(constructs, delimiter=',')

而不是:

construct_list = csv.reader(constructs, delimiter=',')

相关问题 更多 >