在Python中检测范围

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

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

创建一个名为 detector_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)]

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

python list function range intervals
3个回答
2
投票

另一种方法。虽然这种方法的效率不如另一种方法,但由于它是一种练习,所以会更容易遵循。

我在Python中使用了

zip
函数来做一些我在下面解释的事情,你可以检查它这里以了解更多信息。

1。首先对列表数据进行排序,这样就得到:

[2, 4, 5, 6, 7, 8, 10, 12, 13]

2。然后找出列表中递增值的差异。就像

(4-2)
(5-4)
,..如果差异是
<=1
,那么它将成为范围的一部分:

(另外,在前面插入一个

0
,只是为了占第一个元素,使得到的列表长度等于原始列表)

>>> 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 1
1 to 6
6 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]

1
投票

迭代元素并保存每个区间的

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)]

0
投票
def detect_ranges(L):
L = sorted(L)
result = []
lo, hi = L[0], L[0]
for i in L[1:]:

    if i == hi+1:
        hi = i
    else:
        if hi == lo:
            result.append(lo)
        else:
            result.append((lo, hi+1))
        lo = i
        hi = i

if lo == hi:
    result.append(lo)
else:
    result.append((lo, hi+1))

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