【问题标题】:Why sorted list detection does not work in this situation?为什么排序列表检测在这种情况下不起作用?
【发布时间】:2015-05-19 13:23:59
【问题描述】:

我的目标是让 python 代码允许检测列表是否已排序。

我想了解为什么以下代码返回 True 而不是我预期的猜测 False

l = [1, 2, 3, 4, 1, 6, 7, 8, 7]
all(l[i] <= l[i+1] for i in xrange(len(l)-1)) # return "True"

注意事项:

  • 我在 iPython 0.10 中使用 python 2.6.4
  • 我使用非常大的列表,所以我宁愿避免 l == l.sort() 类型的解决方案

为了理解这一点,我已经阅读(并测试)了以下两个主要帖子中的信息:

编辑: 好吧,显然问题只出现在 iPython 内部,而不是仅使用 python 命令行时!

iPython 0.10

In [93]: l = [1, 2, 3, 4, 1, 6, 7, 8, 7]

In [94]: all(l[i] <= l[i+1] for i in xrange(len(l)-1))
Out[94]: True

python 2.6.4

>>> l = [1, 2, 3, 4, 1, 6, 7, 8, 7]
>>> all(l[i] <= l[i+1] for i in xrange(len(l)-1))
False

【问题讨论】:

  • @Ajay:你能说得更具体点吗?
  • 我在 Python 2.6.6 上也得到了 False,无论是 gen exp 版本还是 list comp 版本。我使用 Python 2.5.5 得到了相同的结果。
  • 这可能只是扯淡,但您显示的代码既不返回也不打印任何内容。所以如果你在 REPL 之外的任何地方运行它,你不应该看到“True”或其他任何东西。您是否 100% 确定这是正在运行的代码,并且是产生输出的行?
  • 对我来说似乎是一个 ipython 错误。最新版本是 3.1。我会尝试升级。
  • print all.__module__ 显示什么?如果不是__builtin__,则您正在从不同的模块使用它 - 可能是numpy

标签: python list sorting ipython


【解决方案1】:

我能够在我的机器上重现类似的问题。但是经过挖掘,发现all函数不是内置函数,而是来自numpy(all.__module__ == 'numpy.core.fromnumeric')。

问题在于您创建的是生成器而不是列表。例如:

all(x>5 for x in xrange(3))
# <generator object <genexpr> at 0x1153bf7d0>

all([x>5 for x in xrange(3)])
# False

if all(x>5 for x in xrange(3)):
   print True
else:
   print False
# prints True

if all([x>5 for x in xrange(3)]):
   print True
else:
   print False
# prints False

只需将[...] 添加到您的表达式中:

all([l[i] <= l[i+1] for i in xrange(len(l)-1)])
# False

如果你需要创建一个列表,一个更有效的解决方案是做一个简单的 for 循环:

for i in xrange(len(l)-1):
    if l[i] > l[i+1]:
        result = False
        break
else:
    result = True

如果像我一样,你覆盖了内置的all 函数,你可以通过del all 来恢复它。之后,您应该拥有all.__module__ == '__builtin__'。如果还是不行,就做all = __builtin__.all

【讨论】:

  • 这不是问题 - 这里根本不需要创建 list - genexp 非常好
  • 你用什么版本的python来得到这个输出?
  • @JulienSpronck:很可能您在 ipython 会话的早期运行过 from numpy import *from numpy import all
  • 这个解决方案通过创建一个额外的列表来浪费内存。考虑将其更改为一旦违反任何条件就会中断的循环。
  • @JulienSprock:更大的问题是您和 prodev 仍然看到不同的行为。 prodev 声称all(l[i] &lt;= l[i+1] for i in xrange(len(l)-1)) 返回了true,而您(正确地)声称使用 numpy 它返回一个生成器。因此,您的环境、默认环境和 prodev 正在做的任何事情之间仍然存在一些差异。
【解决方案2】:

您在问题中提供的代码运行良好:

Python 2.7

>>> l = [1, 2, 3, 4, 1, 6, 7, 8, 7]
>>> all(l[i] <= l[i+1] for i in xrange(len(l)-1))
False

Python 3.4

我们将range 替换为xrange...

>>> l = [1, 2, 3, 4, 1, 6, 7, 8, 7]
>>> all(l[i] <= l[i+1] for i in range(len(l)-1))
False

IPython 3.0.0 和 Python 2.7.6

In [1]: l = [1, 2, 3, 4, 1, 6, 7, 8, 7]

In [2]: all(l[i] <= l[i+1] for i in xrange(len(l)-1))
Out[2]: False

【讨论】:

    【解决方案3】:

    最后看来,iPython 0.10 中的可行解决方案是:

    In [93]: l = [1, 2, 3, 4, 1, 6, 7, 8, 7]
    In [100]: all([l[i] <= l[i+1] for i in xrange(len(l)-1)])
    Out[100]: False
    

    编辑: 或者更好:使用已接受答案中提供的循环!

    【讨论】:

    • 该解决方案通过创建一个额外的列表来浪费内存。考虑将其更改为一旦违反任何条件就会中断的循环。
    • @musically_ut 你完全正确 :) Julien Spronck 提出的循环对于我的情况确实似乎是一个更好的解决方案(旧 iPython)
    猜你喜欢
    • 1970-01-01
    • 2017-11-26
    • 2010-12-29
    • 1970-01-01
    • 2021-08-05
    • 2011-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多