Избегать псевдонимов объектов в Python?

Я пытаюсь написать функцию, чтобы проверить, отсортирован ли список (возвращая True или же False). Как я могу избежать нескольких переменных, указывающих на одно и то же?

def is_sorted(t):
    a = t
    a.sort()

Когда я делаю это, он сортирует оба a а также t, Как я могу избежать этого?

7 ответов

Вот O(N) способ сделать это

>>> 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

Это короткие цепи, поэтому, если список не отсортирован в самом начале, это будет очень быстро

Вот простая программа для сравнения некоторых альтернатив

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 (или используйте синтаксис слайса [:]) создать копию исходного списка:

import copy

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

Однако лучшим способом было бы использовать sorted Функция для возврата отсортированной копии списка:

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

Или же: is_sorted = lambda t: sorted(t) == t

Кредит на этот минимальный ответ принадлежит @gnibbler

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

Создав копию своего списка с чем-то вроде этого:

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

Вы можете сделать копию t а потом сортировать, вот так: a = t[:] или используйте sorted, который возвращает новый отсортированный список.

Кроме того, вы можете использовать sortedlist структура от blist, тогда ваш список всегда будет отсортирован.

Это очень плохой способ с точки зрения производительности проверить, что список упорядочен. Вместо этого вы должны выполнить итерацию, проверяя, что каждый элемент больше или равен предыдущему.

Это самый простой способ сделать это... насколько я знаю

      def is_sorted(t):
    a = list(t)
    a.sort()
Другие вопросы по тегам