检测范围 Python

Detect ranges in Python

我正在尝试在我的课程作业中解决这个练习:

创建一个名为 detect_ranges 的函数,它获取一个整数列表作为参数。 然后该函数应该对该列表进行排序,并将该列表转换为另一个列表,其中对用于所有检测到的间隔。 所以 3,4,5,6 被一对 (3,7) 代替。 不属于任何区间的数字只会产生单个数字。 结果列表由这些数字和对组成,以逗号分隔。此功能如何工作的示例:

print(detect_ranges([2,5,4,8,12,6,7,10,13]))
[2,(4,9),10,(12,14)]

我无法理解练习题,也想不出如何检测范围。你们有什么提示或技巧吗?

遍历元素并保存每个区间的start

def detect_ranges(xs):
    it = iter(xs)
    try:
        start = next(it)
    except StopIteration:
        return
    prev = start

    for x in it:
        if prev + 1 != x:
            yield start, prev + 1
            start = x
        prev = x

    yield start, prev + 1

用法:

>>> xs = [2, 4, 5, 6, 7, 8, 10, 12, 13]
>>> ranges = list(detect_ranges(xs))
>>> ranges
[(2, 3), (4, 9), (10, 11), (12, 14)]

如果你想减少单项间隔,如 (2, 3)2,你可以这样做:

>>> ranges = [a if a + 1 == b else (a, b) for a, b in ranges]
>>> ranges
[2, (4, 9), 10, (12, 14)]

另一种方法。虽然这种方法不如另一种有效,但由于它是一种练习,因此会更容易遵循。

我在python中使用了zip函数来做一些我在下面解释的事情,你可以检查一下here了解更多。

1.先对列表数据进行排序,于是得到: [2, 4, 5, 6, 7, 8, 10, 12, 13]

2。然后在列表中找到递增值的差异。喜欢(4-2),(5-4),..如果不一样<=1,那么就是一部分范围:

(另外,在前面插入一个0,只是为了占第1个元素,使得到的列表长度等于原来的列表)

>>> diff = [j-i for i, j in zip(lst[:-1], lst[1:])]
>>> diff.insert(0, 0)
>>> diff
[0, 2, 1, 1, 1, 1, 2, 2, 1]

3。现在在上面的列表中找到差异为 >= 2 的位置。这是为了检测范围:

(同样,在前面插入一个0,只是为了说明第一个元素,并确保它在范围检测中被选中)

>>> ind = [i for i,v in enumerate(diff) if v >= 2]
>>> ind.insert(0, 0)
>>> ind
[0, 1, 6, 7]

所以在您的原始列表中,范围是 0 to 11 to 66 to 7

4。使用获得的 ind 列表将元素组合在一起形成范围:

>>> groups = [lst[i:j] for i,j in zip(ind, ind[1:]+[None])]
>>> groups
[[2], [4, 5, 6, 7, 8], [10], [12, 13]]

5.最后得到你想要的范围:

>>> ranges = [(i[0],i[-1]+1) if len(i)>1 else i[0] for i in groups]
>>> ranges
[2, (4, 9), 10, (12, 14)]

将其全部放在一个函数中 detect_ranges:

def detect_ranges(lst):
    lst = sorted(lst)
    diff = [j-i for i, j in zip(lst[:-1], lst[1:])]
    diff.insert(0, 0)
    
    ind = [i for i,v in enumerate(diff) if v >= 2]
    ind.insert(0, 0)
    
    groups = [lst[i:j] for i,j in zip(ind, ind[1:]+[None])]
    ranges = [(i[0],i[-1]+1) if len(i)>1 else i[0] for i in groups]
    return ranges

示例:

>>> lst = [2,6,1,9,3,7,12,45,46,13,90,14,92]
>>> detect_ranges(lst)
[(1, 4), (6, 8), 9, (12, 15), (45, 47), 90, 92]

>>> lst = [12,43,43,11,4,3,6,6,9,9,10,78,32,23,22,98]
>>> detect_ranges(lst)
[(3, 5), (6, 7), (9, 13), (22, 24), 32, (43, 44), 78, 98]