确定列表中的连续数字(Python)
我正在寻找一种最“pythonic”的方法,来判断一个列表中的数字是否是连续的。简单来说,我有一个数字列表,这些数字是从一个文件夹里收集来的,我需要找出哪些数字是缺失的。
我先把所有的数字收集起来,然后根据范围(开始数字,结束数字+1)生成一个应该存在的数字列表。我很容易就做出了一个可以显示所有缺失数字的程序:
missing = [x for x in existingNumbers if x not in shouldBeNumbers]
问题是,如果我把所有缺失的数字都打印出来,可能会有很多数字可以合并成一个范围(比如1, 2, 3, 4, 7, 10可以简化为1-4, 7, 10),因为可能会有大量的数字缺失。
我尝试了两种方法:
这两种方法中,frameRange是从startFrame到endFrame+1的范围,而frameList是从当前存在的数字生成的列表。
1)
for x in frameRange:
if x not in frameList:
if originalFrame == None:
originalFrame = x
elif originalFrame:
if lastFrame == None:
lastFrame = x
elif lastFrame:
if lastFrame == x-1:
lastFrame = x
else:
if originalFrame != lastFrame:
missingFrames.append(str(originalFrame)+"-"+str(lastFrame))
originalFrame = x
lastFrame = x
else:
missingFrames.append(str(originalFrame))
originalFrame = x
lastFrame = x
if x == endFrame:
if originalFrame != lastFrame:
missingFrames.append(str(originalFrame)+"-"+str(lastFrame))
originalFrame = x
lastFrame = x
else:
missingFrames.append(str(originalFrame))
originalFrame = x
lastFrame = x
2)
i = 0
while i < len(frameRange):
if frameRange[i] in frameList:
i += 1
else:
if i + 1 < len(frameRange):
if frameRange[i + 1] in frameList:
missingFrames.append(str(frameRange[i]))
i += 1
else:
j = 1
while frameRange[i+j] not in frameList:
aheadFrameNumber = int(str(j))
if i + j + 1 < len(frameRange):
j += 1
else:
break
missingFrames.append(str(frameRange[i])+"-"+str(frameRange[aheadFrameNumber]))
if i + aheadFrameNumber + 1 < len(frameRange):
i += aheadFrameNumber + 1
else:
missingFrames.append(str(frameRange[i]))
第一种方法是有效的,但因为它是在检查当前帧的最后一个数字时进行的,所以每当最后一个帧消失时,它就不会把最后缺失的部分添加到列表中。第二种方法我不得不不断用if语句来包裹所有内容,因为在向前移动时总是会出现索引异常。
我觉得我需要退一步,重新思考,并换个方式来处理这个问题。我在想,是否有更好的方法可以在python中实现这个功能,而我还没有想到,因为我不太了解这个函数。这两种方法开始变得有些复杂了。
2 个回答
1
def find_missing_range(my_numbers, range_min, range_max):
expected_range = set(range(range_min, range_max + 1))
return expected_range - set(my_numbers)
def numbers_as_ranges(numbers):
ranges = []
for number in numbers:
if ranges and number == (ranges[-1][-1] + 1):
ranges[-1] = (ranges[-1][0], number)
else:
ranges.append((number, number))
return ranges
def format_ranges(ranges):
range_iter = (("%d" % r[0] if r[0] == r[1] else "%d-%d" % r) for r in ranges)
return "(" + ", ".join(range_iter) + ")"
def main(my_numbers, range_min, range_max):
numbers_missing = find_missing_range(my_numbers, range_min, range_max)
ranges = numbers_as_ranges(numbers_missing)
return format_ranges(ranges)
if __name__ == '__main__':
range_min, range_max = 1, 40
print main([1, 4, 6, 10, 12], range_min, range_max)
print main([1, 2, 3, 4, 10, 20], range_min, range_max)
(2-3, 5, 7-9, 11, 13-40)
(5-9, 11-19, 21-40)
当然可以!请把你想要翻译的内容发给我,我会帮你把它变得简单易懂。
4
试试这样做:
missing=[]
numbers.insert(0, 0) # add the minimum value on begining of the list
numbers.append(41) # add the maximum value at the end of the list
for rank in xrange(0, len(numbers)-1):
if numbers[rank+1] - numbers[rank] > 2:
missing.append("%s-%s"%(numbers[rank] +1 , numbers[rank+1] - 1))
elif numbers[rank+1] - numbers[rank] == 2:
missing.append(str(numbers[rank]+1))
print missing
如果你的 numbers = [1,4,6,10, 12,]
,而你希望的数字范围是从1到40,那么你会得到:
['2-3', '5', '7-9', '11', '13-40']