Existe uma maneira pitônica de verificar se uma lista já está classificada ASC
ouDESC
listtimestamps = [1, 2, 3, 5, 6, 7]
algo assim isttimestamps.isSorted()
retorna True
ou False
.
Quero inserir uma lista de carimbos de data e hora para algumas mensagens e verificar se as transações apareceram na ordem correta.
key
função a ser usada.key=lambda x, y: x < y
faz um bom padrão.def isSorted(x, key = lambda x: x): return all([key(x[i]) <= key(x[i + 1]) for i in xrange(len(x) - 1)])
operator.le
deve ser mais rápido do que o lambdal = [1, 2, 3, 4, 1, 6, 7, 8, 7] all(l[i] <= l[i+1] for i in xrange(len(l)-1))
imprima como resultado:True
xrange
mais, basta usarrange
. ReceboNameError: name 'xrange' is not defined
quando executo esse código. Mudei para usar apenas emrange
vez dexrange
e isso funciona bem. Veja: stackoverflow.com/questions/15014310/…Eu usaria apenas
a menos que seja uma lista muito grande; nesse caso, convém criar uma função personalizada.
se você quiser classificá-lo se não estiver classificado, esqueça a verificação e classifique-a.
e não pense muito sobre isso.
se você deseja uma função personalizada, pode fazer algo como
Isso será O (n) se a lista já estiver classificada (e O (n) em um
for
loop!), Portanto, a menos que você espere que ela não seja classificada (e bastante aleatória) na maioria das vezes, novamente, basta classificar a lista.fonte
Este formulário do iterador é 10-15% mais rápido que o uso da indexação inteira:
fonte
izip
eislice
de ferramentas para torná-lo mais rápido.Uma maneira bonita de implementar isso é usar a
imap
função deitertools
:Essa implementação é rápida e funciona em quaisquer iteráveis.
fonte
is_sorted(iter([1,2,3,2,5,8]))
ou um gerador equivalente. Você precisa usar um iterador independente paratail
, tenteitertools.tee
.iter(x) is x
para iteratorsitertools.imap
foi renomeado para[__builtins__.]map
.Fiz um benchmark
e. Esses benchmarks foram executados em um MacBook Pro 2010 13 "(Core2 Duo 2.66GHz, 4GB 1067MHz DDR3 RAM, Mac OS X 10.6.5).sorted(lst, reverse=True) == lst
foi o mais rápido para listas longas eall(l[i] >= l[i+1] for i in xrange(len(l)-1))
o mais rápido para listas curtasATUALIZAÇÃO: Revisei o script para que você possa executá-lo diretamente em seu próprio sistema. A versão anterior tinha bugs. Além disso, adicionei entradas classificadas e não classificadas.all(l[i] >= l[i+1] for i in xrange(len(l)-1))
sorted(l, reverse=True) == l
all(l[i] >= l[i+1] for i in xrange(len(l)-1))
all(l[i] >= l[i+1] for i in xrange(len(l)-1))
Portanto, na maioria dos casos, há um vencedor claro.ATUALIZAÇÃO: as respostas de aaronsterling (# 6 e # 7) são realmente as mais rápidas em todos os casos. O número 7 é o mais rápido porque não possui uma camada de indireção para procurar a chave.
fonte
enumerate
estão incorretas.enumerate(l[1:])
deve ser substituído porenumerate(l[1:], 1)
enumerate(l[1:])
porenumerate(l[1:], 1)
você pode substituirl[i-1]
porl[i]
.L5=range(100); random.shuffle(L5)
número 5 é comparativamente lento. Nesse caso, o nº 7 modificado é mais rápido no geral codepad.org/xmWPxHQYEu faria isso (roubando muitas respostas aqui [Aaron Sterling, Wai Yip Tung, meio que de Paul McGuire] e principalmente Armin Ronacher ):
Uma coisa boa: você não precisa entender o segundo iterável da série (ao contrário de uma fatia da lista).
fonte
key
.key
deve ser usado para transformar itens em valores comparáveis.Eu uso esse one-liner baseado em numpy.diff ():
Eu realmente não cronometrei isso contra nenhum outro método, mas presumo que seja mais rápido que qualquer método Python puro, especialmente para n grandes, pois o loop em numpy.diff (provavelmente) é executado diretamente em C (subtrações n-1 seguidas por n -1 comparações).
No entanto, você precisa ter cuidado se x for um int não assinado, o que pode causar um estouro silencioso de números inteiros em numpy.diff (), resultando em um falso positivo. Aqui está uma versão modificada:
fonte
Isso é semelhante à resposta principal, mas eu gosto mais porque evita a indexação explícita. Supondo que sua lista tenha o nome
lst
, você pode gerar(item, next_item)
tuplas da sua lista comzip
:No Python 3,
zip
já retorna um gerador, no Python 2 você pode usaritertools.izip
para melhorar a eficiência da memória.Pequena demonstração:
O último falha quando a tupla
(3, 2)
é avaliada.Bônus: verificando geradores finitos (!) Que não podem ser indexados:
Certifique-se de usar
itertools.izip
aqui se você estiver usando o Python 2, caso contrário você perderia o propósito de não precisar criar listas dos geradores.fonte
islice
para otimizar o fatiamento. Também no módulo itertools.all(x <= y for x, y in izip(lst, islice(lst, 1)))
.SapphireSun está certo. Você pode apenas usar
lst.sort()
. A implementação de classificação do Python (TimSort) verifica se a lista já está classificada. Nesse caso, sort () será concluído em tempo linear. Soa como uma maneira Pythonic de garantir que uma lista seja classificada;)fonte
Embora eu ache que não há garantia de que o
sorted
built-in chame sua função cmp comi+1, i
, ele parece fazê-lo no CPython.Então você pode fazer algo como:
Ou assim (sem as declarações if -> EAFP deram errado? ;-)):
fonte
Não é muito pitonico, mas precisamos de pelo menos uma
reduce()
resposta, certo?A variável acumulador simplesmente armazena esse último valor verificado e, se algum valor for menor que o valor anterior, o acumulador é definido como infinito (e, portanto, ainda será infinito no final, pois o 'valor anterior' sempre será maior que o atual).
fonte
Conforme observado por @aaronsterling, a solução a seguir é a mais curta e parece mais rápida quando a matriz é classificada e não muito pequena: def is_sorted (lst): return (classificado (lst) == lst)
Se na maioria das vezes a matriz não for classificada, seria desejável usar uma solução que não varra toda a matriz e retorne False assim que um prefixo não classificado for descoberto. A seguir, é a solução mais rápida que pude encontrar, não é particularmente elegante:
Usando o benchmark de Nathan Farrington, isso obtém um tempo de execução melhor do que o uso do ordenado (lst) em todos os casos, exceto quando executado na grande lista classificada.
Aqui estão os resultados de benchmark no meu computador.
ordenada (lst) == lst solução
Segunda solução:
fonte
Se você deseja o caminho mais rápido para matrizes numpy, use numba , que se você usar conda já deve estar instalado
O código será rápido porque será compilado pela numba
e depois:
fonte
Apenas para adicionar outra maneira (mesmo que exija um módulo adicional)
iteration_utilities.all_monotone
::Para verificar a ordem DESC:
Também existe um
strict
parâmetro se você precisar verificar estritamente (se elementos sucessivos não forem iguais) seqüências monotônicas.Não é um problema no seu caso, mas se suas seqüências contiverem
nan
valores, alguns métodos falharão, por exemplo, com a classificação:Observe que o
iteration_utilities.all_monotone
desempenho é mais rápido em comparação com as outras soluções mencionadas aqui, especialmente para entradas não classificadas (consulte a referência ).fonte
Preguiçoso
fonte
all(a <= b for a, b in zip(l, l[1:]))
l
é um gerador e não suporta fatiamento.Python 3.6.8
fonte
Maneira mais simples:
fonte
O valor de redução derivado é uma tupla de três partes de ( sortedSoFarFlag , firstTimeFlag , lastElementValue ). É inicialmente começa com (
True
,True
,None
), que é também utilizado como o resultado de uma lista vazia (considerado como classificados porque não existem elementos de fora-de-fim). À medida que processa cada elemento, ele calcula novos valores para a tupla (usando valores anteriores da tupla com o próximo elementValue):O resultado final da redução é uma tupla de:
O primeiro valor é aquele em que estamos interessados, então usamos isso
[0]
para obter o resultado reduzido.fonte
Como não vejo essa opção acima, vou adicioná-la a todas as respostas. Vamos denotar a lista até
l
, então:fonte
Uma solução usando expressões de atribuição (adicionadas no Python 3.8):
Dá:
fonte
Essa é, de fato, a maneira mais curta de fazer isso usando a recursão:
se estiver classificado, imprimirá True; caso contrário, imprimirá False
fonte
RuntimeError: maximum recursion depth exceeded
para listas longas. Tenteany_list = range(1000)
.Que tal este ? Simples e direto.
fonte
Definitivamente funciona em Python 3 e acima para números inteiros ou seqüências de caracteres:
==================================================== ===================
Outra maneira de descobrir se a lista fornecida está classificada ou não
fonte