如何判断列表中是否包含连续的数字

23

我想测试一个列表是否包含连续的整数且没有重复的数字。 例如,如果我有:

l = [1, 3, 5, 2, 4, 6]

它应该返回True。

如何检查列表是否包含最多n个连续数字,而不修改原始列表? 我考虑了复制列表,并删除出现在原始列表中的每个数字,如果列表为空,则返回True。

有更好的方法吗?


你的例子中答案应该是什么? - saulspatz
我很困惑为什么你的测试用例应该返回“True”,因为5和2不是连续的。 - wnnmaw
这些条目是整数吗?它们是非负数或严格正数吗? - Blender
在R中,它将是any(diff(sort(x)) == 1) & all(table(x) == 1),但我还不会Python,所以我很想看看它是如何完成的。我正在尽可能地翻译,以便学习两种语言。 - Pierre L
如果数字是连续的,就不能重复。因此第二个条件是多余的。当检查 [1,2,2,3] 时,期望的输出是什么?如果答案是 True,请重新措辞问题。 - Pynchia
“如何检查列表是否包含最多n个连续数字”是什么意思?这似乎是一个单独的问题,与“我想测试列表是否包含连续整数且没有重复项”不同。如果n==2,那么[1, 1, 3, 4][1, 3, 4]的答案应该是什么? - ruancomelli
13个回答

31

对于整个列表,它应该尽可能简单

sorted(l) == list(range(min(l), max(l)+1))

这样可以保留原始列表,但是如果您的列表特别长,则制作副本(然后进行排序)可能会很昂贵。

请注意,在Python 2中,您可以简单地使用下面的代码,因为range返回一个list对象。在3.x及更高版本中,该函数已更改为返回一个range对象,因此在与sorted(l)比较之前需要显式转换为list

sorted(l) == range(min(l), max(l)+1))

要检查n个条目是否连续且不重复,就会变得有点复杂:

def check(n, l):
    subs = [l[i:i+n] for i in range(len(l)) if len(l[i:i+n]) == n]
    return any([(sorted(sub) in range(min(l), max(l)+1)) for sub in subs])

1
这两个条件怎么测试啊?我觉得你需要重新阅读一下问题。首先要注意的是,你的“解决方案”没有返回一个逻辑值。 - Pierre L
1
@wnnmaw 这个解决方案还需要再微调一下。测试正在检查所有数字是否连续。OP 正在检查 'n' 是否连续。然后,您必须添加第二个条件的检查,“没有数字重复”。 - Pierre L
我也添加了一个答案。 - Pierre L
1
整个列表,应该是 sorted(l) == list(range(min(l), max(l)+1)) 吗? - Zuabi
1
@Zuabi,是的,对于Python 3.x及更高版本,您需要显式进行列表转换。我已经更新了我的答案。 - wnnmaw
显示剩余6条评论

4
我们可以使用已知的数学公式来检查连续性,假设最小数字始终从1开始。
sum of consecutive n numbers 1...n = n * (n+1) /2 


  def check_is_consecutive(l):
        maximum = max(l)
        if sum(l) == maximum * (maximum+1) /2 : 
             return True
        return False

1
针对 [1,1,4,4,5] 失败。 - Isaac Turner
1
@IsaacTurner 根据问题描述,数字不会重复。是的,如果有重复的话,就像你所提到的那样,它将无法工作。 - Shankar
问题要求测试连续非重复数字。输入可以是任何整数列表。 - Isaac Turner
是的,您需要对列表进行去重(很容易),然后检查下面的函数是否为真。 maximum = max(l) minimum=min(l) sum(l) == maximum * (maximum + 1) / 2 -((minimum-1)*(minimum)/2) - KeepLearning

3
第一段代码可以去重但保持原有顺序:
from itertools import groupby, count

l = [1,2,4,5,2,1,5,6,5,3,5,5]

def remove_duplicates(values):
    output = []
    seen = set()
    for value in values:
        if value not in seen:
            output.append(value)
            seen.add(value)
    return output

l = remove_duplicates(l) # output = [1, 2, 4, 5, 6, 3]

下一步是确定哪些是有序的,取自这里的代码:
def as_range(iterable):
    l = list(iterable)
    if len(l) > 1:
        return '{0}-{1}'.format(l[0], l[-1])
    else:
        return '{0}'.format(l[0])

l = ','.join(as_range(g) for _, g in groupby(l, key=lambda n, c=count(): n-next(c)))

l 的输出为:1-2,4-6,3

您可以根据需要自定义函数以获得所需的输出。


你可以直接使用 l = list(set(l))。这将会移除所有的重复项。 - Nikhil John

1

一旦您确认列表中没有重复项,只需计算min(l)max(l)之间的整数之和:

def check(l):
    total = 0
    minimum = float('+inf')
    maximum = float('-inf')

    seen = set()

    for n in l:
        if n in seen:
            return False

        seen.add(n)

        if n < minimum:
            minimum = n

        if n > maximum:
            maximum = n

        total += n

    if 2 * total != maximum * (maximum + 1) - minimum * (minimum - 1):
        return False

    return True

1
import numpy as np
import pandas as pd    

(sum(np.diff(sorted(l)) == 1) >= n) & (all(pd.Series(l).value_counts() == 1))

我们测试两种情况,首先通过找到排序列表的迭代差异np.diff(sorted(l))来测试是否有n个连续整数。最后,我们测试value_counts()是否都为1,表示没有重复项。

0
def solution(A):
    counter = [0]*len(A)
    limit = len(A)
    for element in A:
        if not 1 <= element <= limit:
            return False
        else:
            if counter[element-1] != 0:
                return False
            else:
                counter[element-1] = 1

    return True

0

我把你的查询分成了两个部分,第一部分是A部分:“列表包含最多n个连续数字”,这是第一行:if len(l) != len(set(l)):

第二部分是B部分,将列表拆分为可能更短的列表,并检查它们是否连续。

def example (l, n):
    if len(l) != len(set(l)):  # part a
        return False
    for i in range(0, len(l)-n+1):  # part b
        if l[i:i+3] == sorted(l[i:i+3]):
            return True
    return False

l = [1, 3, 5, 2, 4, 6]
print example(l, 3)

0
l = [1, 3, 5, 2, 4, 6]
from itertools import chain


def check_if_consecutive_and_no_duplicates(my_list=None):
    return all(
        list(
            chain.from_iterable(
                [
                    [a + 1 in sorted(my_list) for a in sorted(my_list)[:-1]],
                    [sorted(my_list)[-2] + 1 in my_list],
                    [len(my_list) == len(set(my_list))],
                ]
            )
        )
    )

将列表中除最后一个数字(6)以外的任何数字加1,并检查结果是否在列表中。对于最大的数字(6),选择它前面的数字(5),加1并检查结果(6)是否在列表中。


0

列表必须排序!

lst = [9,10,11,12,13,14,15,16]

final = True if len( [ True for x in lst[:-1] for y in lst[1:] if x + 1 == y ] ) == len(lst[1:]) else False

我不知道这有多高效,但应该能解决问题。


0
该函数的输入是您的列表。如果数字重复,此函数将返回False。 即使列表不以1开头,下面的代码也可以正常工作。
def check_is_consecutive(l):
    """
    sorts the list and 
    checks if the elements in the list are consecutive
    This function does not handle any exceptions.
    returns true if the list contains consecutive numbers, else False
    """
    l = list(filter(None,l))
    l = sorted(l)
    if len(l) > 1:
        maximum = l[-1]
        minimum = l[0] - 1
        if minimum == 0:
            if sum(l) == (maximum * (maximum+1) /2): 
                return True
            else:
                return False
        else:
            if sum(l) == (maximum * (maximum+1) /2) - (minimum * (minimum+1) /2) : 
                return True
            else:
                return False
    else:
        return True

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接