确定列表中的序列号(Python)

时间:2011-08-16 14:17:15

标签: python list sequential

我正在尝试找到最pythonic的方法来查明列表中的数字是否是连续的。为了给出一些背景知识,我有一个存储在文件夹中的数字列表,我需要找出哪些数字丢失。

我收集所有数字,然后从范围(开头,结尾+ 1)制作另一个列表,其中应该包含哪些数字。我很容易找到一些东西向我展示所有缺失的数字:

missing = [x for x in existingNumbers if x not in shouldBeNumbers]

问题在于,如果我打印出所有这些,可以压缩很多数字(即1,2,3,4,7,10可以打印为1-4,7,10)因为可能会丢失大量的数字。

我尝试了两种方法:

对于这两种方式,frameRange是range(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 个答案:

答案 0 :(得分:3)

尝试这样的事情

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

答案 1 :(得分: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)