我一直在努力编写一个函数来分割两个 numpy 数组 (a1,a2) 中的间隔,其中包含完整范围 0, 6000 的间隔。 a1 和 a2 的间隔不能以任何方式重叠,如果某个间隔在 a1 中的某些值中,则它不能在 a2 中,反之亦然 我需要一个函数 shuffle 需要给定的间隔,a1 中的间隔部分移动到 a2 ,间隔的部分移动到 a2 a2 中的内容被移动到 a1 中。 最后,对二维数组进行排序和压缩,确保当间隔接近时数组的大小不会不必要地增长。例如,如果数组有 [[0,1],[1,3]],则需要将其压缩为 [[0,3]]
我尝试了不同的方法,但无法得到它的矢量化变体。我已经成功编写了一个单元测试测试用例,说明输出应该是什么样子。
import unittest
class TestCases(unittest.TestCase):
def test_invertRange(self):
def shuffle(interval, a1, a2):
#implement here
pass
return a1, a2
a1 = np.array([[1,300],[500,600],[5000,6000]])
a2 = np.array([[0,1],[300,500],[600,5000]])
a1,a2 = shuffle(np.array([[0.5,1.5]]),a1,a2)
self.assertEqual(a1,np.array([[0.5,1],[1.5,300],[500,600],[5000,6000]]))
self.assertEqual(a2,np.array([[0,0.5],[1,1.5],[300,500],[600,5000]]))
suma1 = np.sum(a1[:,1] - a1[:,0])
suma2 =np.sum(a2[:,1] - a2[:,0])
total = suma1 + suma2
# the sum of intervals should always equal the sum of the range 0,6000
self.assertEqual(total, np.sum(np.linspace(0,6001)))
a1,a2 = shuffle(np.array([[0.5,1.5]]),a1,a2)
self.assertEqual(a1,np.array([[1,300],[500,600],[5000,6000]]))
self.assertEqual(a2,np.array([[0,1],[300,500],[600,5000]]))
suma1 = np.sum(a1[:,1] - a1[:,0])
suma2 =np.sum(a2[:,1] - a2[:,0])
total = suma1 + suma2
# the sum of intervals should always equal the sum of the range 0,6000
self.assertEqual(total, np.sum(np.linspace(0,6001)))
你可以这样做;
import numpy as np
def compact_intervals(intervals):
"""Compact overlapping or contiguous intervals."""
if not intervals.size:
return intervals
intervals = intervals[intervals[:, 0].argsort()] # Sort by the start of intervals
compacted = [intervals[0]]
for current in intervals[1:]:
prev = compacted[-1]
if current[0] <= prev[1]: # Overlapping or contiguous intervals
compacted[-1] = [prev[0], max(prev[1], current[1])] # Merge intervals
else:
compacted.append(current)
return np.array(compacted)
def invert_intervals(interval, source, target):
"""Move intervals from source to target and vice versa."""
# Determine overlap and adjust intervals
new_source = []
new_target = []
start, end = interval
for iv in source:
if iv[1] <= start or iv[0] >= end: # No overlap
new_source.append(iv)
else: # Some overlap
if iv[0] < start:
new_target.append([iv[0], start])
if iv[1] > end:
new_target.append([end, iv[1]])
new_source.append([max(iv[0], start), min(iv[1], end)])
for iv in target:
if not (iv[1] <= start or iv[0] >= end): # Overlap
new_source.append([max(iv[0], start), min(iv[1], end)])
else:
new_target.append(iv)
# Compact and sort results
compacted_source = compact_intervals(np.array(new_source))
compacted_target = compact_intervals(np.array(new_target))
return compacted_source, compacted_target
def shuffle(interval, a1, a2):
a1, a2 = invert_intervals(interval, a1, a2)
a2, a1 = invert_intervals(interval, a2, a1)
return compact_intervals(a1), compact_intervals(a2)