Avoid object aliasing in python?
I am trying to write a function to check whether a list is sorted (returning True
or False
). How can I avoid multiple variables pointing to the same thing?
def is_sorted(t):
a = t
a.sort()
When I do that, it sorts both a
and t
. How can I avoid开发者_JS百科 this?
Here is the O(n) way to do it
>>> from itertools import islice, izip
>>> def is_sorted(L):
... return all(i<=j for i,j in izip(L, islice(L,1,None)))
...
>>> is_sorted(range(50))
True
>>> is_sorted(range(50)+[20])
False
It shortcircuits, so if the list is unsorted right near the beginning it will be very fast
Here is a simple program to compare some of the alternatives
import random
import time
from itertools import islice, izip
def is_sorted1(L): # 0.0006s
return all(i<=j for i,j in izip(L, islice(L,1,None)))
def is_sorted2(L): # 0.117s
return all(L[i] < L[i+1] for i in range(len(L)-1) )
def is_sorted3(L): # 2.344s
return L == sorted(L)
def is_sorted4(L): # 0.0002s
return all(L[i] < L[i+1] for i in xrange(len(L)-1) )
A = [range(random.randrange(100000)) for i in range(100)]
for a in A:
random.shuffle(a)
for f in is_sorted1, is_sorted2, is_sorted3, is_sorted4:
s=time.time()
for a in A:
f(a)
print time.time() - s
EDIT: Please see this answer for the proper way to do it. I'll leave my answer here for posterity (what's the correct way of handling this situation?), but it should not be considered the best answer to the question, even if it is a correct answer to the question.
To answer your specific question, you can use copy.copy
(or use the slice syntax [:]
) to create a copy of the original list:
import copy
def is_sorted(t):
a = copy.copy(t) # could also do: a = t[:]
a.sort()
return a == t
However, a better method would be to use the sorted
function to return a sorted copy of the list:
def is_sorted(t):
return sorted(t) == t
Or: is_sorted = lambda t: sorted(t) == t
by creating a copy of your list with something like this:
def is_sorted(t):
a = t[:] # create a copy
a.sort()
Credit for this minimal answer belongs to @gnibbler
is_sorted = all(q[i] < q[i+1] for i in xrange(len(q)-1) )
You can either make a copy of t
and then sort, like so: a = t[:]
, or use sorted
, which returns a new sorted list.
Alternatively, you could make use of the sortedlist
structure from blist, then your list will always be sorted.
This is a very poor way, in terms of performance, to check that a list is ordered. You should instead iterate over it checking that each element is greater or equal to the previous.
精彩评论