在给定范围内的两个 2D numpy 数组之间获取间隔切割

问题描述 投票:0回答:1

我一直在努力编写一个函数来分割两个 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)))

python arrays numpy vectorization
1个回答
0
投票

你可以这样做;

  1. 确定给定区间的哪些部分属于a1,哪些部分属于a1 属于a2。
  2. 在a1和a2之间移动适当的部分。
  3. 排序并 压缩 a1 和 a2 以确保没有不必要的间隔 存在。
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)

© www.soinside.com 2019 - 2024. All rights reserved.