Skip to main content
 首页 » 编程设计

python之更具体的 OOP 条件之Python

2025年05月04日9jackei

我上一个问题的延续,使用第二个答案 - http://tinyurl.com/n9dybgb

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

感谢@Hugh Bothwell - 我目前有这段代码:

class ChromoSegments: 
    def __init__(self, ChromoSegments_args=None): 
        #Creates an empty default dict list which can be added to in the style "chromo[start,end]", and will stay ordered 
        self.segments = defaultdict(list) 
        #If a list is passed to the constructor you can add values to your list depending on conditions in '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 
    #function for adding positions to the expos list 
    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)) 
        #collision with preceding element 
        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() 
 
    #convert results back into text files of positions 
    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”和“newpos_list”,然后丢弃所有与现有元素有任何重叠的匹配项。请有人在 add_seg 函数中建议一组不同的/更好的 if 语句,以便仅丢弃完全包含在现有元素中的匹配项?我真的很难让语法正确!非常感谢!

示例列表:

expos_list = [[1, 20, 40], [1, 60, 80]] 
newpos_list = [[1, 12, 25], [1, 22, 38], [1, 75, 90], [1, 100, 150]] 

所以,在一个成功的过程之后,我想要一个最终的 expos_list(记住第一个数字(目前在所有情况下都是 1)可以是任何东西:

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

请您参考如下方法:

我试一试:

START = 1 
END = 2 
expos_list = [[1, 20, 40], [1, 60, 80]] 
newpos_list = [[1, 12, 25], [1, 22, 38], [1, 75, 90], [1, 100, 150]] 
# sort the new list 
expos_list.extend(newpos_list) 
expos_list.sort(lambda l1, l2: cmp(l1[0], l2[0]) or (l1[0] == l2[0] and (cmp(l1[1], l2[1]) or (l1[1] == l2[1] and (cmp(l1[2], l2[2])))))) 
 
# remove and print the overlaps 
i = 0 
l = expos_list 
while i < len(l) - 1: 
    if l[i][END] > l[i + 1][START]: 
        print 'overlap', l[i], l[i+1] 
        if l[i][START] <= l[i+1][START] and l[i][END] >= l[i+1][END]: 
            # i+1 is in i 
            l.pop(i+1) 
        elif l[i][START] >= l[i+1][START] and l[i][END] <= l[i+1][END]: 
            # i is in i+1 
            l.pop(i) 
        else: 
            # there is a partial overlap 
            i += 1 
    else: 
        i += 1 
 
# overlap [1, 12, 25] [1, 20, 40] 
# overlap [1, 20, 40] [1, 22, 38] 
# [1, 22, 38] # removed 
# overlap [1, 60, 80] [1, 75, 90] 
 
# outcome 
print expos_list 
# [[1, 12, 25], [1, 20, 40], [1, 60, 80], [1, 75, 90], [1, 100, 150]] 

此代码删除所有完全重叠的元素并打印所有重叠

以下行可用于 Python 3:

lambda l1, l2: l1[0] < l2[0] or (l1[0] == l2[0] and (l1[1] < l2[1] or (l1[1] == l2[1] and (l1[2] <= l2[2]))))