Python:在迭代时将范围添加到范围列表

我遇到问题并希望任何人都可以给我一个小技巧来克服它。Python:在迭代时将范围添加到范围列表

我有一个2D-python-list(83行和3列)。前两列是间隔的开始和结束位置。第三列是数字索引(例如:9.68)。该列表按第3列进行反向排序。 我想要得到所有与最高索引不重叠的区间。

这里是排序列表的示例:

504 789 9.68 

503 784 9.14

505 791 8.78

499 798 8.73

1024 1257 7.52

1027 1305 7.33

507 847 5.86

这里是我的尝试:

# Define a function that test if 2 intervals overlap 

def overlap(start1, end1, start2, end2):

return not (end1 < start2 or end2 < start1)

best_list = [] # Create a list that will store the best intervals

best_list.append([sort[0][0],sort[0][1]]) # Append the first interval of the sorted list

# Loop through the sorted list

for line in sort:

local_start, local_end = line.rsplit("\s",1)[0].split()

for i in range(len(best_list)):

best_start = best_list[i][0]

best_end = best_list[i][1]

test = overlap(int(best_start), int(best_end), int(local_start), int(local_end))

if test is False:

best_list.append([local_start, local_end])

我也得到:

best_list = [(504, 789),(1024, 1257),(1027, 1305)] 

但我想:

best_list = [(504, 789),(1024, 1257)] 

谢谢!

回答:

嗯,我有一些关于你的代码的问题。由于sort包含字符串,因此该行append([sort[0][0],sort[0][1]])做了什么你期望的?

无论如何,你的问题主要是当你的列表中存在多个元素时,只要其中一个通过重叠测试就可以被添加到列表中(不是你想要的)。例如。当两个(504, 789),(1024, 1257)都存在时,(1027, 1305)将被插入到列表中,因为它与(504, 789)进行比较时通过了测试。

于是,我做了一些改变,现在它似乎按预期方式工作:

best_list = [] # Create a list that will store the best intervals 

best_list.append(sort[0].rsplit(" ", 1)[0].split()) # Append the first interval of the sorted list

# Loop through the sorted list

for line in sort:

local_start, local_end = line.rsplit("\s", 1)[0].split()

flag = False # <- flag to check the overall overlapping

for i in range(len(best_list)):

best_start = best_list[i][0]

best_end = best_list[i][1]

test = overlap(int(best_start), int(best_end), int(local_start), int(local_end))

print(test)

if test:

flag = False

break

flag = True

if flag:

best_list.append([local_start, local_end])

主要思想是检查每一个元素,如果通过了所有重叠的测试,那么添加它(的最后一行我的代码)。之前没有。

回答:

假设你解析你的CSV和已经与[(start, stop, index), ....][(int, int, float), ...]列表,那么你可以用下面的排序是:

from operator import itemgetter 

data = sorted(data, key=itemgetter(2), reverse=True)

这意味着你排序第三的位置,并以相反的顺序从返回的结果最大到最小。

def nonoverlap(data): 

result = [data[0]]

for cand in data[1:]:

start, stop, _ = cand

current_span = range(start, stop+1)

for item in result:

i, j, _ = item

span = range(i, j+1)

if (start in span) or (stop in span):

break

elif (i in current_span) or (j in current_span):

break

else:

result.append(cand)

return result

然后用上面的函数就可以得到想要的结果。对于提供的代码片段,您将获得[(504, 789, 9.68), (1024, 1257, 7.52)]。我在这里使用的事实,你可以使用1 in range(0, 10)这将返回True。虽然这是一个天真的实现,但您可以将其用作起点。如果只想返回开始停止return [i[:2] for i in result]替换返回行。

注意:另外我想补充说,你的代码有一个逻辑错误。您在每次比较后做出决定,但必须在与已经存在于您的所有元素best_list进行比较后做出决定。这就是为什么(504, 789)(1027, 1305)通过你的测试,但不应该。我希望这封信会帮助你。

以上是 Python:在迭代时将范围添加到范围列表 的全部内容, 来源链接: utcz.com/qa/262005.html

回到顶部