关于别名:避免python中的对象别名?

Avoid object aliasing in python?

我正在尝试编写一个函数来检查列表是否已排序(返回TrueFalse)。 如何避免多个变量指向同一个东西?

1
2
3
def is_sorted(t):
    a = t
    a.sort()

当我这样做时,它会对at进行排序。 我怎么能避免这个?


这是O(n)方法

1
2
3
4
5
6
7
8
>>> 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

它是短路的,所以如果列表在开头附近未分类,它将非常快

这是一个比较一些替代方案的简单程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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


编辑:请参阅此答案以了解正确的方法。我会在这里留下我的答案给后人(处理这种情况的正确方法是什么?),但它不应该被认为是问题的最佳答案,即使这是对问题的正确答案。

要回答您的具体问题,您可以使用copy.copy(或使用切片语法[:])来创建原始列表的副本:

1
2
3
4
5
6
import copy

def is_sorted(t):
    a = copy.copy(t) # could also do: a = t[:]
    a.sort()
    return a == t

但是,更好的方法是使用sorted函数返回列表的排序副本:

1
2
def is_sorted(t):
    return sorted(t) == t

或者:is_sorted = lambda t: sorted(t) == t


这个最小答案的功劳属于@gnibbler

1
is_sorted = all(q[i] < q[i+1] for i in xrange(len(q)-1) )


通过使用以下内容创建列表的副本:

1
2
3
def is_sorted(t):  
    a = t[:]  # create a copy
    a.sort()


您可以复制t然后进行排序,如下所示:a = t[:],或使用sorted,它返回一个新的排序列表。

或者,您可以使用blist中的sortedlist结构,然后您的列表将始终排序。


就性能而言,这是一种非常糟糕的方式,用于检查列表是否已订购。您应该迭代检查每个元素是否大于或等于前一个元素。