开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜