Избегать псевдонимов объектов в Python? - PullRequest
7 голосов
/ 06 января 2011

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

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

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

Ответы [ 6 ]

9 голосов
/ 06 января 2011

Вот 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
6 голосов
/ 06 января 2011

РЕДАКТИРОВАТЬ : Пожалуйста, смотрите этот ответ , чтобы узнать, как это сделать. Я оставлю здесь свой ответ для потомков (как правильно обращаться с этой ситуацией?), Но он не должен считаться лучшим ответом на вопрос, даже если это правильный ответ на вопрос .


Чтобы ответить на ваш конкретный вопрос, вы можете использовать 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

3 голосов
/ 06 января 2011

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

is_sorted = all(q[i] < q[i+1] for i in xrange(len(q)-1) )
3 голосов
/ 06 января 2011

, создав копию вашего списка примерно так:

def is_sorted(t):  
    a = t[:]  # create a copy
    a.sort()
2 голосов
/ 06 января 2011

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

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

0 голосов
/ 06 января 2011

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

...