问题
My goal is to have python code allowing to detect if a list is sorted or not.
I would like to understand why the following code return True instead of my expected guess 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"
Notes:
- I'm using python 2.6.4 inside iPython 0.10
- I use very huge list so I'd prefer to avoid
solution of type
l == l.sort()
In the way to understand this I already read (and test) info from the main two following post:
- https://stackoverflow.com/a/3755251/4716013
- https://stackoverflow.com/a/4710776/4716013
EDIT: OK apparently the problem appear inside iPython ONLY, not when using only python command line!
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
回答1:
I was able to reproduce a similar problem on my machine. However, after digging, it occurred that the all function was not the built-in function but came from numpy (all.__module__ == 'numpy.core.fromnumeric').
The problem is that you are creating a generator rather than a list. For example:
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
Simply add [...] to your expression:
all([l[i] <= l[i+1] for i in xrange(len(l)-1)])
# False
If it is the case that you need to create a list, a more efficient solution would be to do a simple for loop:
for i in xrange(len(l)-1):
if l[i] > l[i+1]:
result = False
break
else:
result = True
If like me, you overrode the built-in all function, you can do del all to recover it. After that, you should have all.__module__ == '__builtin__'. If that's still not the case, just do all = __builtin__.all
回答2:
The code you've presented in the question works fine:
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
We substitute range for 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 with 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:
Finally it appear that a working solution in iPython 0.10 would be:
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
EDIT: Or better: use a loop as presented in the accepted answer!
来源:https://stackoverflow.com/questions/30326927/why-sorted-list-detection-does-not-work-in-this-situation