检测范围 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 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]
我正在尝试在我的课程作业中解决这个练习:
创建一个名为 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 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]