【问题标题】:How to check if consecutive elements of array are evenly spaced?如何检查数组的连续元素是否均匀分布?
【发布时间】:2019-11-07 04:21:56
【问题描述】:

例如:

[1,2,3,4,5,6] -> True
[1,2,3,5,6] -> False

我想我可以这样做:

if len(set([arr[x] - arr[x - 1] for x in range(1, len(arr))])) > 1:
    print('not equally spaced')

我想知道是否有更好的方法?

【问题讨论】:

  • 更好究竟是什么意思?
  • 获取前两个元素的区别。然后遍历数组,如果任何一对有不同的差异则停止。
  • @StephenRauch 计算效率更高。理想情况下。我认为 Barmar 的答案可能正是我想要的。
  • 一件事是您不需要构建列表。只需删除括号。
  • @learningthemachine,然后使用 numpy。

标签: python


【解决方案1】:

您可以检查差异是否都相同(使用 numpy.diff):

import numpy as np
a = np.array([1,2,3,4,5,6])
b = np.array([1,2,3,5,6])

all(np.diff(a)==np.diff(a)[0])  # --> True
all(np.diff(b)==np.diff(b)[0])  # --> False

【讨论】:

    【解决方案2】:

    这就是我最终做的......

    def same_dist_elems(arr):
        diff = arr[1] - arr[0]
        for x in range(1, len(arr) - 1):
            if arr[x + 1] - arr[x] != diff:
                return False
        return True
    

    感谢 Barmar,但他只发表评论而不是回答

    【讨论】:

    • 这是最直接的解决方案,但您应该将小于 2 的列表作为特殊情况处理。否则diff = arr[1] - arr[0] 将引发 IndexError。
    • 我正在尝试使用值 a,b,c 如下,但我没有得到输出 def same_dist_elems(a, b, c): arr = (a, b, c) diff = arr[1] - arr[0] for x in range(1, len(arr) - 1): if arr[x + 1] - arr[x] != diff: return False return True # 测试代码 same_dist_elems( 2、4、6)
    【解决方案3】:

    试试这个,列表是连续的

    • 最后一项与第一项之差加1必须等于列表长度
    • 列表长度与集合长度必须匹配以排除重复条目
    • 需要对列表进行排序才能正常工作。

    代码

    def check_consecutive(input_list):
        input_list = sorted(input_list)
        return (input_list[-1] - input_list[0]) + 1 == len(input_list) and (len(input_list) == len(set(input_list))
    
    check_consecutive([1,2,3,4,5,6]) # True
    check_consecutive([1,2,3,5,6])   # False
    

    就像评论提到的那样,上面的代码只适用于 1 个单位的间距,如果 input_list 已经排序,我们可以省略排序列表部分

    为了使它适用于任何空间单元,我们可以尝试下面的代码。 它首先根据 input_list 空间单元创建理想的均匀空间列表,然后根据 input_list 进行比较。下面的代码假设 input_list 已经排序

    def check_evenly_space(input_list):
        if len(input_list)==1:
            return False
        space = input_list[1] - input_list[0]
        if space==0:
            return False
        return list(range(input_list[0], input_list[-1] + space, space)) == input_list
    
    check_evenly_space([1,2,3,4,5,6]) # True
    check_evenly_space([1,2,3,5,6])   # False
    check_evenly_space([2,4,6,8,10])  # True
    check_evenly_space([2,4,6,7,10])  # False
    

    【讨论】:

    • “均匀间隔”,但该空间不一定是一个单位。我认为您可以通过在某处乘以前两个元素的差异来解决此问题。
    • 我不这么认为。如果列表项不是严格相邻的,那么它们可能会有间隙,导致大小比较不起作用。例如。 [1, 2, 5] 将被接受,因为代码无法区分它和 [1, 3, 5]。并且对列表进行排序有点问题,因为无论如何您都需要确保项目是有序的。 [3, 5, 1] 无效!
    • 这将对[3][5, 5, 9] 等列表抛出错误。
    • @kaya3,为此添加了固定
    【解决方案4】:

    一个简单的解决方案是将列表与范围进行比较。要保存将范围转换为列表,我们可以使用zipall。这可能不是最有效的解决方案,但仍然需要 O(n) 时间和 O(1) 辅助空间。

    def list_is_evenly_spaced(lst):
        # special case: a list with 0, 1 or 2 elements is evenly spaced
        if len(lst) <= 2:
            return True
    
        first = lst[0]
        gap = lst[1] - first
        # special case: a constant list is evenly spaced
        if gap == 0:
            return all(x == first for x in lst)
    
        # general case: an evenly spaced list equals a range
        r = range(first, first + gap*len(lst), gap)
        return all(x == y for x,y in zip(lst, r))
    

    特殊情况说明,需单独处理:

    • 由 0、1 或 2 个元素组成的列表始终是均匀分布的。要不均匀地间隔,必须有两个不同的间隙,这意味着至少三个元素。
    • 常量列表总是等间距的,因为每个间隙都是 0。但是,构造一个间隙为 0 的范围是无效的。

    【讨论】:

      【解决方案5】:

      你可以用 numpy 轻松做到这一点

      import numpy as np
      np.diff(a) == len(a)-1
      
      True
      

      如果速度是一个问题,请确保

      type(a)
      <type 'numpy.ndarray'>
      

      np.array(a)

      【讨论】:

        【解决方案6】:

        你可以试试这个

        def ContiguousElem(arr):
            ss = set() 
            for i in arr: ss.add(i)
            count = 1
            curr = arr[0] - 1
            while curr in ss:
                count += 1
                curr -= 1
            curr = arr[0] + 1
        
            while curr in ss: 
                count += 1
                curr += 1
            return (count == len(ss)) 
        arr1 = [1,2,3,4,5,6]
        arr2 = [1,2,3,5,6]
        if ContiguousElem(arr1): print("Yes") 
        else: print("No") 
        if ContiguousElem(arr2): print("Yes") 
        else: print("No") 
        
        o/p : Yes
              No
        

        【讨论】:

        • 为什么要将数组转换为集合?
        • 这个算法并不简单,所以你应该解释它是如何工作的。
        • 这里我只是想将 'arr[]' 的元素推送到哈希表/集合中,然后选择第一个元素并继续将其值增加 1,直到找到不存在的值哈希表。其他元素也是如此。哈希表中存在的元素(通过此过程获得)的计数。如果计数等于散列大小,则打印“是”,否则为“否”。这样我们可以将时间复杂度降低到 O(n)。
        猜你喜欢
        • 2017-04-14
        • 2020-05-08
        • 1970-01-01
        • 1970-01-01
        • 2011-05-05
        • 1970-01-01
        • 2013-08-02
        • 2016-03-20
        • 1970-01-01
        相关资源
        最近更新 更多