【问题标题】:python 3.6 bug or i am nutspython 3.6错误或者我疯了
【发布时间】:2020-05-29 19:03:07
【问题描述】:

检查列表中的项目是否连续。

[True for x in lst[:-1] for y in lst[1:] if x + 1 == y]

所以列表[1, 2, 3, 4, 5] 返回[True, True, True, True],表示该列表是连续的。

列表[1,2,3,4,4] 返回[True, True, True, True] 表示该列表是连续的,但不是。

为每个语句做证明

lst = [1,2,3,4,4]


def consecutive(lst):    
    lst.sort()
    return [True for x in lst[:-1] for y in lst[1:] if x + 1 == y]


print(consecutive(lst))

some_list = []
for i,j in zip(lst[:-1], lst[1:]):
    if i+1 == j:
        some_list.append(True)
    else:
        some_list.append(False)

print(some_list)

我在这里错过了什么?

【问题讨论】:

  • 我只是复制了您的代码并运行并得到了您所期望的结果
  • 你在 anaconda 上运行了什么?
  • 问题是代码使用列表理解做同样的事情,另一个使用“for语句”但输出不同
  • 列表理解 [True for ...] 不可能返回除了一个充满 Trues 的列表之外的任何东西 - 任何其他值从何而来?问题是您没有并行迭代lst[:-1]lst[1:](您需要zip() 来执行此操作),而是循环遍历列表中的每一对值 - 任何包含 N 和N+1 都存在于列表中的某处导致True
  • FWIW 您可以将整个 if i+1 == j: ... 块简化​​为 some_list.append(i+1 == j),然后轻松转换为理解 some_list = [i+1 == j for i, j in zip(lst[:-1], lst[1:])]

标签: python python-3.x list list-comprehension


【解决方案1】:

您的列表理解正在执行嵌套循环,而不是并行循环。它在两个切片的叉积上循环。如果您删除 if 并返回 xy 本身的值,您可以看到这一点。

>>> [(x, y) for x in lst[:-1] for y in lst[1:]]
[(1, 2), (1, 3), (1, 4), (1, 4), (2, 2), (2, 3), (2, 4), (2, 4), (3, 2), (3, 3), (3, 4), (3, 4), (4, 2), (4, 3), (4, 4), (4, 4)]

只要成对的元素是连续的,结果就会包含True;当它们不连续时,它不会为结果添加任何内容。有 4 对是连续的,所以这就是你得到的结果。

如果您只想测试相邻元素,请在推导式中使用zip()

>>> [True for x, y in zip(lst[:-1], lst[1:]) if x + 1 == y]
[True, True, True]

如果你想在列表中同时返回TrueFalse,你不应该使用if,你应该返回测试的结果:

>>> [(x + 1 == y) for x, y in zip(lst[:-1], lst[1:])]
[True, True, True, False]

【讨论】:

    【解决方案2】:

    我不认为你的代码在做你认为它正在做的事情。

    我稍微调整了一下,结果如下:

    >>> [[x, y] for x in lst[:-1] for y in lst[1:]]
    [[1, 2], [1, 3], [1, 4], [1, 4], [2, 2], [2, 3], [2, 4], [2, 4], [3, 2], [3, 3], [3, 4], [3, 4], [4, 2], [4, 3], [4, 4], [4, 4]]
    

    您的列表理解实际上是一个 2D 循环,您只是过滤所有组合以获取 True 的半随机数。

    在您的情况下,[1, 2][2, 3][3, 4][3, 4] 满足条件 x + 1 == y

    考虑重写consecutive,这里有一个快速的想法,例如:

    def consecutive(lst):
        return [lst[i] + 1 == lst[i + 1] for i in range(len(lst) - 1)]
        # implicitly does the same thing as return [True if lst[i] + 1 == lst[i + 1] else False for i in range(len(lst) - 1)]
    

    【讨论】:

      【解决方案3】:

      我会将第一个函数改写如下:

      lst = [1,2,3,4,4]
      
      
      def consecutive(lst):    
          lst.sort()
          return [True if lst[:-1][i] +1 ==lst[1:][i] else False  for i,x in enumerate(lst[:-1])  ]  
      
      print(consecutive(lst))
      [True, True, True, False]
      

      这表明前三个元素是连续的。
      如果您只想将连续对设置为True,请使用以下代码:

      lst = [1,2,3,4,4]
      
      
      def consecutive(lst):    
          lst.sort()
          return [True for i,x in enumerate(lst[:-1]) if lst[:-1][i] +1 ==lst[1:][i]   ]
      
      
      print(consecutive(lst))
      [True, True, True]
      

      【讨论】:

      • 我认为你没有抓住重点。第一个应该是[True, True, True, False],和第二个一样是@wjandrea
      • @notacorn 在原始代码中,他没有将False 用于第一个函数。所以我认为他在问为什么它显示四个True,尽管它有三个连续的对。无论如何我已经更新了代码。
      【解决方案4】:

      试试这个:

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

      【讨论】:

        【解决方案5】:

        你真的只需要一次迭代来完成这个

        见下面的代码:

        def consecutive(list_):
            n = len(list_)
            list_.sort()
            ans = [True if list_[i-1]+1 == list_[i] else False for i in range(1,n)]
            return ans
        
        list_ = [2,5,1,2,6,3,7,7]
        print(consecutive(list_))
        
        [True, False, True, False, True, True, False]
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2023-04-08
          • 2014-03-25
          • 1970-01-01
          • 2018-02-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多