为了账号安全,请及时绑定邮箱和手机立即绑定

查找范围值列表中的空白

查找范围值列表中的空白

MMMHUHU 2023-07-27 09:53:35
我在其他编程语言(ruby、C++、JS 等)中发现了许多类似的问题,但在 Python 中却没有。因为Python有例如itertools我想知道我们是否可以在Python中更优雅地做同样的事情。假设我们有一个“完整范围”,[1,100]然后是“完整范围”内/匹配“完整范围”的范围子集:[10,50][90,100][1,9]在本例中,我们如何提取未覆盖的位置[51,89]?这是一个玩具示例,在我的真实数据集中,范围高达数千。
查看完整描述

3 回答

?
动漫人物

TA贡献1815条经验 获得超10个赞

这是一个使用以下方法的巧妙解决方案itertools.chain:我假设输入范围不重叠。如果确实如此,则需要首先使用范围并集算法对其进行简化。

from itertools import chain


def range_gaps(a, b, ranges):

    ranges = sorted(ranges)

    flat = chain((a-1,), chain.from_iterable(ranges), (b+1,))

    return [[x+1, y-1] for x, y in zip(flat, flat) if x+1 < y]

range_gaps(1, 100, [[10, 50], [90, 100]])个例子:

  • 首先对范围进行排序,以防它们尚未按顺序排列。如果保证它们是有序的,则不需要这一步。

  • 然后flat是一个迭代器,它将给出序列0, 10, 50, 90, 100, 101

  • 由于flat是惰性评估的,并通过迭代消耗它,zip(flat, flat)因此给出了像 之类的对序列(0, 10), (50, 90), (100, 101)

  • 所需的范围就像(1, 9), (51, 89)和 的情况一样(100, 101),应该给出一个空范围,因此它被丢弃。



查看完整回答
反对 回复 2023-07-27
?
哈士奇WWW

TA贡献1799条经验 获得超6个赞

假设列表仅包含整数,并且子范围按递增顺序且不重叠,您可以使用以下代码。


此代码将一一获取所有子范围,并将与原始完整范围及其之前的子范围进行比较,以找到丢失的范围。


[start,end]=[1,100]

chunks=[[25,31],[7,15],[74,83]]


print([r for r in [[start,chunks[0][0]-1] if start!=chunks[0][0] else []] + [[chunks[i-1][1]+1, chunks[i][0]-1] for i in range(1,len(chunks))]+[[chunks[-1][1]+1,end] if end!=chunks[-1][1] else []] if r])

输入


[1,100]

[[7,15],[25,31],[74,83]]

输出


[[1, 6], [16, 24], [32, 73], [84, 100]]

如果不能保证子范围的递增顺序。您可以包含以下行来对块进行排序。


chunks.sort(key=lambda x: x[0])


查看完整回答
反对 回复 2023-07-27
?
眼眸繁星

TA贡献1873条经验 获得超9个赞

这是一个通用的解决方案:


def gap(N, ranges):

    ranges=[(min1, max1), (min2, (max2), ......, (minn, maxn)]

    

    original=set(range(N))

           

    for i in ranges:

        original=original-set(range(i[0], i[1]))


    return original


查看完整回答
反对 回复 2023-07-27
  • 3 回答
  • 0 关注
  • 90 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信