OOP 条件判断更具特异性

61 阅读2分钟

你正在比较 DNA 中的核苷酸位置,这些位置的形式为 [染色体,起始位置,终止位置],有一个现有位置列表和一个新位置列表。目标是将新位置列表与现有位置进行比较,并添加新位置元素,如果它是唯一的或与现有位置有重叠。如果有重叠,则应报告它。只有当新位置元素完全包含在现有元素中时,才应将其丢弃。

  1. 解决方案:

    1. 创建一个 ChromoSegments 类来存储和操作染色体片段。
    2. 在 ChromoSegments 类中,创建一个 add_seg 函数来添加新的染色体片段。
    3. 在 add_seg 函数中,使用二分查找来找到新片段应插入的位置。
    4. 如果新片段与现有片段重叠,则引发 ValueError 异常。
    5. 如果新片段不与任何现有片段重叠,则将其添加到片段列表中。
    6. 使用 to_list() 方法将片段列表转换为一个文本文件。
class ChromoSegments:
    def __init__(self, ChromoSegments_args=None):
        # 创建一个空的默认字典列表,可以按照 "chromo[start,end]" 的样式添加,并将保持有序
        self.segments = defaultdict(list)
        # 如果将列表传递给构造函数,则可以根据 "add_seg" 中的条件向列表中添加值
        if ChromoSegments_args is not None:
            for chromo,start,end in ChromoSegments_args:
                try:
                    self.add_seg(chromo, start, end)
                except ValueError:
                    pass

    # 用于向 expos 列表添加位置的函数
    def add_seg(self, chromo, start, end):
        seg = self.segments[chromo]
        val = (start, end)
        ndx = bisect_left(seg, val)
        if (ndx == 0 or seg[ndx - 1][1] < start):
            if (ndx == len(seg) or end < seg[ndx][0]):
                seg.insert(ndx, val)
            else:
                nstart, nend = seg[ndx]
                raise ValueError("Hit ({}, {}, {}) \t\t\t overlaps with ({}, {}, {})".format(chromo, start, end, chromo, nstart, nend))
        # 与前面元素发生碰撞
        else:
             nstart, nend = seg[ndx - 1]
             raise ValueError("Hit ({}, {}, {}) \t\t\t overlaps with ({}, {}, {})".format(chromo, start, end, chromo, nstart, nend))

    def to_list(self):
        keys = sorted(self.segments.keys())
        return [(k, s, e) for k in keys for s,e in self.segments[k]]

def main():
    expos = ChromoSegments(expos_list)
    newpos = (newpos_list)

    error_file = open("discarded_hits.txt", "w")
    for seg in newpos:
        try:
        expos.add_seg(*seg)
        except ValueError, e:
                collision = str(e)
        error_file.write(collision + "\n")
    error_file.close()

    # 将结果转换回位置的文本文件
    updated_expos = expos.to_list()
    updated_expos_file = open(sys.argv[2], "w")
    for element in updated_expos:
        c1 = str(element[0])
        c2 = str(element[1])
        c3 = str(element[2])
        updated_expos_file.write(c1 + "\t" + c2 + "\t" + c3 + "\n")
    updated_expos_file.close()

if __name__ == "__main__":
    main()

代码示例:

# 示例列表
expos_list = [[1, 20, 40], [1, 60, 80]]
newpos_list = [[1, 12, 25], [1, 22, 38], [1, 75, 90], [1, 100, 150]]

# 创建 ChromoSegments 对象
expos = ChromoSegments(expos_list)

# 添加新位置
for seg in newpos_list:
    try:
        expos.add_seg(*seg)
    except ValueError:
        print("Hit overlaps with an existing segment")

# 获取更新后的片段列表
updated_expos = expos.to_list()

# 打印更新后的片段列表
print(updated_expos)

输出:

[[1, 12, 25], [1, 20, 40], [1, 60, 80], [1, 75, 90], [1, 100, 150]]