【问题标题】:How to see if the list contains consecutive numbers如何查看列表是否包含连续数字
【发布时间】:2015-11-06 20:31:09
【问题描述】:

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

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

它应该返回 True。

如何在不修改原始列表的情况下检查列表是否包含最多 n 个连续数字? 我想过复制列表并删除原始列表中出现的每个数字,如果列表为空,那么它将返回 True。

有没有更好的方法来做到这一点?

【问题讨论】:

  • 你的例子中的答案应该是什么?
  • 我很困惑为什么你的测试用例应该返回True,5和2不连续
  • 条目是整数吗?它们是非负数还是严格正数?
  • 在 R 中应该是 any(diff(sort(x)) == 1) & all(table(x) == 1) 但我还不知道 Python,所以我有兴趣看看它是如何完成的。我正在尝试尽可能地进行翻译以学习两者。
  • 如果数字是连续的,则不能有重复的。所以第二个条件是多余的。检查[1,2,2,3] 时所需的输出是什么?如果答案是True,请改写问题

标签: python list


【解决方案1】:

对于整个列表,它应该就像

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

【讨论】:

  • 不使用排序还有其他方法吗?
  • 如何测试这两种情况?我认为你需要重新阅读这个问题。首先考虑您的“解决方案”不返回逻辑。
  • @wnnmaw 这个解决方案需要进一步调整。该测试正在检查所有数字是否连续。 OP 正在检查“n”是否是连续的。然后你必须为第二个条件“没有重复数字”添加一个检查。
  • 整个列表不应该是sorted(l) == list(range(min(l), max(l)+1))吗?
  • @Zuabi,是的,对于 Python 3.x 及更高版本,您需要明确地进行列表转换。我已经更新了答案
【解决方案2】:

第一个代码删除重复但保持顺序:

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]

下一组是识别哪些是有序的,取自here

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))。那将删除所有重复项
【解决方案3】:

这是一个非常简单的解决方案,无需使用任何导入:

range = range(10)
L = [1,3,5,2,4,6]
L = sorted(L, key = lambda L:L)
range[(L[0]):(len(L)+L[0])] == L

>>True

这适用于任何长度的数字列表并检测重复项。 基本上,您正在创建列表可能位于的范围,编辑该范围以匹配列表的标准(长度、起始值)并进行快照比较。我想出了这个我正在编码的纸牌游戏,我需要检测手中的顺子/运行,它似乎工作得很好。

【讨论】:

  • 不建议使用range作为变量,因为它有自己的功能。此外,在复制您的解决方案时,会生成以下错误:TypeError: 'range' object is not callable
  • key = lambda L:L 毫无意义。恒等函数是默认的排序键函数。使用 lambda 实现标识函数只会减慢速度。此外,sorted 函数创建一个列表,并通过调用列表的.sort 方法对其进行排序。所以你应该直接打电话给L.sort(),而不是浪费时间和内存来创建一个新列表。
【解决方案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,4,4,5] 失败
  • @IsaacTurner 根据问题,没有重复数字。是的,如果有重复,它不会像你提到的那样工作。
  • 该问题要求对连续的非重复数字进行测试。输入可以是任何整数列表。
  • 是的,您需要对列表进行重复数据删除(简单),然后检查以下函数是否为真maximum = max(l)minimum=min(l)sum(l) == maximum * (maximum + 1) / 2 -((minimum-1)*(minimum)/2)
【解决方案5】:

验证列表没有重复项后,只需计算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

【讨论】:

    【解决方案6】:
    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,表示没有重复。

    【讨论】:

      【解决方案7】:

      我将您的查询分为两部分 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)
      

      【讨论】:

        【解决方案8】:
        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
        

        【讨论】:

          【解决方案9】:

          此函数的输入是您的列表。如果数字重复,此函数返回 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
          

          【讨论】:

            【解决方案10】:

            1.

            l.sort()

            2.

            for i in range(0,len(l)-1)))
               print(all((l[i+1]-l[i]==1)
            

            【讨论】:

            • 请在添加答案时更清楚,并使用格式化程序快捷方式,例如:使用反引号`格式化代码
            【解决方案11】:

            列表必须排序!

            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
            

            我不知道这有多有效,但它应该可以解决问题。

            【讨论】:

              【解决方案12】:

              带排序

              在 Python 3 中,我使用这个简单的解决方案:

              def check(lst):
                  lst = sorted(lst)
                  if lst:
                      return lst == list(range(lst[0], lst[-1] + 1))
                  else:
                      return True
              

              请注意,在对列表进行排序后,它的最小值和最大值将免费作为第一个 (lst[0]) 和最后一个 (lst[-1]) 元素。 如果参数为空,我将返回True,但这个决定是任意的。选择最适合您的用例。

              在这个解决方案中,我们首先对参数进行排序,然后将其与另一个我们知道的连续且没有重复的列表进行比较。

              不排序

              在其中一个答案中,OP 评论询问是否可以在不对列表进行排序的情况下做同样的事情。这很有趣,这是我的解决方案:

              def check(lst):
                  if lst:
                      r = range(min(lst), max(lst) + 1) # *r* is our reference
                      return (
                          len(lst) == len(r)
                          and all(map(lst.__contains__, r))
                          # alternative: all(x in lst for x in r)
                          # test if every element of the reference *r* is in *lst*
                      )
                  else:
                      return True
              

              在此解决方案中,我们构建了一个参考范围r,它是ints 的连续(因此不重复)序列。有了这个,我们的测试很简单:首先我们通过与参考比较来检查lst 具有正确数量的元素(不是更多,表示重复,也不是更少,表示间隙)。然后我们检查引用中的每个元素是否也在lst 中(这就是all(map(lst.__contains__, r)) 正在做的事情:它遍历r 并测试它的所有元素是否都在lts 中)。

              【讨论】:

                【解决方案13】:
                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)是否在列表中。

                【讨论】:

                  猜你喜欢
                  • 2017-09-11
                  • 1970-01-01
                  • 1970-01-01
                  • 2013-09-30
                  • 2017-08-17
                  • 2019-07-28
                  • 1970-01-01
                  • 1970-01-01
                  • 2020-07-21
                  相关资源
                  最近更新 更多