Eu preciso da seguinte função:
Entrada : alist
Saída :
True
se todos os elementos na lista de entrada forem avaliados iguais entre si usando o operador de igualdade padrão;False
de outra forma.
Desempenho : é claro, prefiro não incorrer em custos indiretos desnecessários.
Eu acho que seria melhor:
- percorrer a lista
- comparar elementos adjacentes
- e
AND
todos os valores booleanos resultantes
Mas não tenho certeza de qual é a maneira mais pitônica de fazer isso.
A falta de recurso de curto-circuito afeta apenas uma entrada longa (mais de 50 elementos) que possui elementos desiguais desde o início. Se isso ocorrer com bastante frequência (quantas vezes depende de quanto tempo as listas podem ser), é necessário um curto-circuito. O melhor algoritmo de curto-circuito parece ser o @KennyTM checkEqual1
. Paga, no entanto, um custo significativo por isso:
- até 20x em listas quase idênticas de desempenho
- desempenho de até 2,5x em listas curtas
Se as entradas longas com elementos desiguais iniciais não ocorrerem (ou ocorrerem suficientemente raramente), não será necessário um curto-circuito. Então, de longe, o mais rápido é a solução @Ivo van der Wijk.
a == b
ou idêntico como ema is b
?functools.reduce(operator.eq, a)
não ter sido sugerido.Respostas:
Método geral:
Uma linha:
Também uma linha:
A diferença entre as 3 versões é a seguinte:
checkEqual2
conteúdo deve ser lavável.checkEqual1
echeckEqual2
pode usar quaisquer iteradores, mascheckEqual3
deve receber uma entrada de sequência, geralmente contêineres concretos, como uma lista ou tupla.checkEqual1
pára assim que uma diferença é encontrada.checkEqual1
contém mais código Python, é menos eficiente quando muitos dos itens são iguais no começo.checkEqual2
echeckEqual3
sempre executa operações de cópia O (N), elas levarão mais tempo se a maior parte da sua entrada retornar Falso.checkEqual2
echeckEqual3
é mais difícil adaptar a comparação dea == b
paraa is b
.timeit
resultado, para Python 2.7 e (somente s1, s4, s7, s9 devem retornar True)Nós temos
Nota:
fonte
obj.__eq__
quandolhs is rhs
e otimizações fora de ordem para permitir um curto-circuito nas listas classificadas mais rapidamente.itertools
receita que eu adicionei como resposta. Pode valer a pena jogar isso na sua matriz de tempo :-).Uma solução mais rápida do que usar set () que funciona em seqüências (não iteráveis) é simplesmente contar o primeiro elemento. Isso pressupõe que a lista não está vazia (mas isso é trivial para verificar e decidir qual o resultado em uma lista vazia)
alguns benchmarks simples:
fonte
x.count(next(x)) == len(x)
para que funcione em qualquer contêiner x? Ahh .. nm, acabei de ver que .count está disponível apenas para seqüências. Por que não é implementado para outros contêineres embutidos? A contagem dentro de um dicionário é inerentemente menos significativa do que dentro de uma lista?count
não é implementado para iterables, e não por quelen
não está disponível para iteradores. A resposta é provavelmente que é apenas uma supervisão. Mas é irrelavante para nós, porque o padrão.count()
para sequências é muito lento (python puro). A razão pela qual sua solução é tão rápida é que ela depende do C-implementadocount
porlist
. Portanto, suponho que qualquer iterável que implemente ocount
método em C se beneficiará da sua abordagem.A maneira mais simples e elegante é a seguinte:
(Sim, isso funciona mesmo com a lista vazia! Isso ocorre porque este é um dos poucos casos em que python possui semântica lenta.)
Em relação ao desempenho, isso falhará o mais rápido possível, portanto é assintoticamente ideal.
fonte
checkEqual1
. Não sei por que.first=myList[0]
all(x==first for x in myList)
, talvezfirst=myList[0]
colocará umaIndexError
em uma lista vazia, para que os comentaristas que estavam falando sobre a otimização que mencionei tenham que lidar com o caso extremo de uma lista vazia. No entanto, o original é bom (x==myList[0]
é bom dentro doall
porque nunca é avaliado se a lista estiver vazia).Um trabalho de comparação de conjuntos:
Usar
set
remove todos os elementos duplicados.fonte
Você pode converter a lista em um conjunto. Um conjunto não pode ter duplicatas. Portanto, se todos os elementos na lista original forem idênticos, o conjunto terá apenas um elemento.
fonte
len(set(input_list)) == 1
?Pelo que vale a pena, isso apareceu recentemente na lista de discussão python-ideas . Acontece que já existe uma receita de ferramentas para fazer isso: 1
Supostamente, ele executa muito bem e tem algumas propriedades agradáveis.
1 Em outras palavras, não posso receber o crédito por ter encontrado a solução - nem posso ter o crédito por encontrá- la.
fonte
return next(g, f := next(g, g)) == f
(from py3.8 of course)Aqui estão duas maneiras simples de fazer isso
usando set ()
Ao converter a lista em um conjunto, os elementos duplicados são removidos. Portanto, se o comprimento do conjunto convertido for 1, isso implica que todos os elementos são iguais.
Aqui está um exemplo
usando all ()
Isso comparará (equivalência) o primeiro elemento da lista de entrada com todos os outros elementos da lista. Se todos forem equivalentes, True será retornado, caso contrário, False será retornado.
Aqui está um exemplo
PS Se você está verificando se a lista inteira é equivalente a um determinado valor, você pode subitituir o valor para input_list [0].
fonte
len(set(a))
em uma lista de 10.000.000 de elementos levou 0,09 s, enquanto o desempenhoall
demorou 0,9 s (10 vezes mais).Essa é outra opção, mais rápida do que
len(set(x))==1
para listas longas (usa curto-circuito)fonte
Esta é uma maneira simples de fazer isso:
Isso é um pouco mais complicado, pois gera sobrecarga de chamada de função, mas a semântica é mais claramente explicada:
fonte
for elem in mylist[1:]
. Duvido que melhora muito a velocidade, já que eu achoelem[0] is elem[0]
que o intérprete provavelmente pode fazer essa comparação muito rapidamente.Verifique se todos os elementos são iguais ao primeiro.
np.allclose(array, array[0])
fonte
Duvido que este seja o "mais pitonico", mas algo como:
faria o truque.
fonte
for
loop pode ser transformado em Pythonicif any(item != list[0] for item in list[1:]): return False
, com exatamente a mesma semântica.Se você estiver interessado em algo um pouco mais legível (mas é claro que não tão eficiente), tente:
fonte
Converta a lista no conjunto e encontre o número de elementos no conjunto. Se o resultado for 1, ele possui elementos idênticos e, se não, os elementos na lista não são idênticos.
fonte
Em relação ao uso
reduce()
comlambda
. Aqui está um código funcional que, pessoalmente, acho muito melhor do que algumas das outras respostas.Retorna uma tupla em que o primeiro valor é o booleano se todos os itens forem iguais ou não.
fonte
[1, 2, 2]
): ele não leva em consideração o valor booleano anterior. Isso pode ser corrigido substituindox[1] == y
porx[0] and x[1] == y
.Eu faria:
como
any
paradas pesquisar na iterable assim que encontra umaTrue
condição.fonte
all()
, por que não usarall(x == seq[0] for x in seq)
? parece mais Python e deve executar a mesmafonte
Funciona no Python 2.4, que não possui "todos".
fonte
for k in j: break
é equivalente anext(j)
. Você também poderia ter feitodef allTheSame(x): return len(list(itertools.groupby(x))<2)
se não se importasse com eficiência.Pode usar mapa e lambda
fonte
Ou use o
diff
método numpy:E para ligar para:
Resultado:
fonte
not np.any(np.diff(l))
poderia ser um pouco mais rápido.Ou use o método diff de numpy:
E para ligar para:
Resultado:
Verdade
fonte
Você pode fazer:
É bastante irritante que o python faça com que você importe os operadores
operator.and_
. A partir do python3, você precisará também importarfunctools.reduce
.(Você não deve usar esse método, pois ele não será interrompido se encontrar valores não iguais, mas continuará examinando a lista inteira. Ele está incluído aqui apenas como resposta para a integridade.)
fonte
O próximo irá causar um curto-circuito:
fonte
reduce(lambda a,b:a==b, [2,2,2])
os rendimentosFalse
... Eu editei, mas desta forma não é muito maisMude a lista para um conjunto. Então, se o tamanho do conjunto for apenas 1, eles deverão ter sido os mesmos.
fonte
Há também uma opção recursiva Python pura:
No entanto, por algum motivo, em alguns casos, é duas ordens de magnitude mais lenta que outras opções. Vindo da mentalidade da linguagem C, esperava que isso fosse mais rápido, mas não é!
A outra desvantagem é que há um limite de recursão no Python que precisa ser ajustado neste caso. Por exemplo, usando isso .
fonte
Você pode usar
.nunique()
para encontrar o número de itens exclusivos em uma lista.fonte
você pode usar
set
. Ele fará um conjunto e removerá elementos repetitivos. Depois verifique se não possui mais de 1 elemento.Exemplo:
fonte