Estou tentando criar uma função que compare várias variáveis com um número inteiro e produza uma sequência de três letras. Fiquei me perguntando se havia uma maneira de traduzir isso em Python. Então diga:
x = 0
y = 1
z = 3
mylist = []
if x or y or z == 0 :
mylist.append("c")
if x or y or z == 1 :
mylist.append("d")
if x or y or z == 2 :
mylist.append("e")
if x or y or z == 3 :
mylist.append("f")
que retornaria uma lista de:
["c", "d", "f"]
É algo assim possível?
python
if-statement
comparison
match
boolean-logic
user1877442
fonte
fonte
1
em (tupla)any
/all
funções. Por exemplo:all([1, 2, 3, 4, False])
retornará Falsoall([True, 1, 2, 3])
retornará Verdadeiroany([False, 0, 0, False])
retornará Falsoany([False, 0, True, False])
retornará Verdadeiroif x == 0 or 1:
, o que obviamente é semelhanteif x or y == 0:
, mas pode ser um pouco confuso para iniciantes. Dado o grande volume de "Por que meux == 0 or 1
trabalho não está ?" Eu prefiro usar essa pergunta como nosso alvo duplicado canônico para essas perguntas.0
,0.0
ouFalse
. Você pode escrever facilmente um código errado, que fornece a resposta "certa".Respostas:
Você entende mal como expressões booleanas funcionam; eles não funcionam como uma sentença em inglês e acho que você está falando da mesma comparação para todos os nomes aqui. Você está procurando:
x
ey
são avaliados de outra forma por conta própria (False
se0
, deTrue
outra forma).Você pode reduzi-lo usando um teste de contenção em relação a uma tupla :
ou melhor ainda:
usar a
set
para tirar proveito do teste de associação de custo constante (in
leva um tempo fixo, independentemente do operando do lado esquerdo).Quando você usa
or
, o python vê cada lado do operador como expressões separadas . A expressãox or y == 1
é tratada como primeiro um teste booleano ex
, se for False, a expressãoy == 1
é testada.Isso ocorre devido à precedência do operador . O
or
operador tem uma precedência mais baixa que o==
teste, portanto, este último é avaliado primeiro .No entanto, mesmo que não fosse esse o caso, e a expressão
x or y or z == 1
fosse realmente interpretada como(x or y or z) == 1
alternativa, isso ainda não faria o que você espera.x or y or z
avaliaria o primeiro argumento que é 'verdade', por exemplo, nãoFalse
numérico 0 ou vazio (consulte expressões booleanas para obter detalhes sobre o que o Python considera falso em um contexto booleano).Portanto, para os valores
x = 2; y = 1; z = 0
,x or y or z
seria resolvido2
, porque esse é o primeiro valor verdadeiro nos argumentos. Então2 == 1
seriaFalse
, mesmo quey == 1
fosseTrue
.O mesmo se aplicaria ao inverso; testando vários valores contra uma única variável;
x == 1 or 2 or 3
falharia pelas mesmas razões. Usex == 1 or x == 2 or x == 3
oux in {1, 2, 3}
.fonte
set
versão. As tuplas são muito baratas para criar e iterar. Na minha máquina, pelo menos, as tuplas são mais rápidas que os conjuntos, desde que o tamanho da tupla esteja em torno de 4-8 elementos. Se você precisar digitalizar mais do que isso, use um conjunto, mas se estiver procurando por um item de 2 a 4 possibilidades, uma tupla é ainda mais rápida! Se você pode mandar para o caso mais provável de ser o primeiro na tupla, a vitória é ainda maior: (meu teste:timeit.timeit('0 in {seq}'.format(seq=tuple(range(9, -1, -1))))
)set
notação literal para este teste não é uma economia, a menos que o conteúdo doset
literal também seja literal, certo?if 1 in {x, y, z}:
não é possível armazenar em cache oset
porquex
,y
ez
pode mudar, portanto, qualquer solução precisa criar umtuple
ou aset
partir do zero, e eu suspeito que qualquer economia de pesquisa que você possa obter ao verificar a associação seria inundada por um maiorset
tempo de criação.in [...]
ouin {...}
) só funciona se o conteúdo da lista ou conjunto são literais imutáveis também.Seu problema é mais facilmente resolvido com uma estrutura de dicionário como:
fonte
d = "cdef"
que leva aMyList = ["cdef"[k] for k in [x, y, z]]
map(lambda i: 'cdef'[i], [x, y, z])
[x, y, z]
Conforme declarado por Martijn Pieters, o formato correto e mais rápido é:
Usando o conselho dele, você agora teria instruções if separadas, para que o Python leia cada instrução, seja ela anterior
True
ou nãoFalse
. Tal como:Isso funcionará, mas se você se sentir confortável usando dicionários (veja o que eu fiz lá), poderá limpar isso, criando um dicionário inicial mapeando os números para as letras desejadas e usando apenas um loop for:
fonte
A maneira direta de escrever
x or y or z == 0
éMas acho que você não gosta. :) E assim é feio.
A outra maneira (melhor) é:
BTW muitos
if
s poderia ser escrito como algo parecido com istofonte
dict
chave em vez de uma chave, você receberá erros porque o valor de retorno de.append
éNone
e a chamadaNone
fornece umAttributeError
. Em geral, eu concordo com este método, no entanto.filter
seria melhor do quemap
, uma vez que irá retornar apenas instâncias onde avalia lambda para trueany(v == 0 for v in (x, y, z))
Se você é muito preguiçoso, pode colocar os valores dentro de uma matriz. Tal como
Você também pode colocar os números e letras em um dicionário e fazê-lo, mas isso provavelmente é MUITO mais complicado do que simplesmente declarações if. É isso que você ganha por tentar ser preguiçoso demais :)
Mais uma coisa, sua
será compilado, mas não da maneira que você deseja. Quando você simplesmente coloca uma variável em uma instrução if (exemplo)
o programa irá verificar se a variável não é nula. Outra maneira de escrever a afirmação acima (que faz mais sentido) é
Bool é uma função embutida em python que basicamente executa o comando de verificar uma instrução booleana (se você não sabe o que é isso, é o que está tentando fazer na sua instrução if agora :))
Outra maneira preguiçosa que encontrei é:
fonte
list
é um Python embutido; use outro nome, comoxyz
por exemplo. Por que você constrói a lista em quatro etapas quando você pode executar uma, ou sejaxyz = [x, y, z]
? Não use listas paralelas, use um ditado. Em suma , esta solução é muito mais complicada do que a ThatGuyRussell . Também para a última parte, por que não fazer uma compreensão, ou sejaany(v == 0 for v in (x, y, z))
? Também matrizes são outra coisa em Python.Para verificar se um valor está contido em um conjunto de variáveis, você pode usar os módulos embutidos
itertools
eoperator
.Por exemplo:
Importações:
Declarar variáveis:
Crie o mapeamento de valores (na ordem que você deseja verificar):
Use
itertools
para permitir a repetição das variáveis:Por fim, use a
map
função para criar um iterador:Em seguida, ao verificar os valores (na ordem original), use
next()
:etc ...
Isso tem uma vantagem sobre o
lambda x: x in (variables)
porqueoperator
é um módulo embutido e é mais rápido e eficiente do que o uso dolambda
qual é necessário criar uma função personalizada no local.Outra opção para verificar se existe um valor diferente de zero (ou Falso) em uma lista:
Equivalente:
fonte
Set é a boa abordagem aqui, porque ordena as variáveis, qual parece ser seu objetivo aqui.
{z,y,x}
é{0,1,3}
qualquer que seja a ordem dos parâmetros.Dessa forma, toda a solução é O (n).
fonte
Todas as excelentes respostas fornecidas aqui concentram-se nos requisitos específicos do pôster original e na
if 1 in {x,y,z}
solução apresentada por Martijn Pieters.O que eles ignoram é a implicação mais ampla da pergunta:
como testar uma variável em relação a vários valores?
A solução fornecida não funcionará para ocorrências parciais se estiver usando seqüências de caracteres, por exemplo:
Teste se a sequência "Wild" está em vários valores
ou
para esse cenário, é mais fácil converter em uma string
Deve-se notar, no entanto, como mencionado por
@codeforester
, que as fronteiras das palavras são perdidas com esse método, como em:as três letras
rot
existem combinadas na lista, mas não como uma palavra individual. Testar a "podridão" falharia, mas se um dos itens da lista fosse "apodrecer no inferno", isso também falharia.Como resultado, tenha cuidado com seus critérios de pesquisa se estiver usando esse método e esteja ciente de que ele tem essa limitação.
fonte
Eu acho que isso vai lidar melhor com isso:
Resultado:
fonte
Se você deseja usar as instruções if, else, a seguir é outra solução:
fonte
fonte
Esse código pode ser útil
fonte
Você pode tentar o método mostrado abaixo. Neste método, você terá a liberdade de especificar / inserir o número de variáveis que deseja inserir.
fonte
Solução de uma linha:
Ou:
fonte
Talvez você precise de uma fórmula direta para o conjunto de bits de saída.
Vamos mapear para bits:
'c':1 'd':0xb10 'e':0xb100 'f':0xb1000
Relação de isc (é 'c'):
Use matemática se a fórmula https://youtu.be/KAdKCgBGK0k?list=PLnI9xbPdZUAmUL8htSl6vToPQRRN3hhFp&t=315
[c]:
(xyz=0 and isc=1) or (((xyz=0 and isc=1) or (isc=0)) and (isc=0))
[d]:
((x-1)(y-1)(z-1)=0 and isc=2) or (((xyz=0 and isd=2) or (isc=0)) and (isc=0))
...
Conecte essas fórmulas seguindo a lógica:
and
é a soma dos quadrados das equaçõesor
é o produto de equaçõese você terá uma equação total de soma expressa e você tem a fórmula total de soma
então soma & 1 é c, soma & 2 é d, soma & 4 é e, soma & 5 é f
Depois disso, você pode formar uma matriz predefinida, onde o índice dos elementos da string corresponderia à string pronta.
array[sum]
dá-lhe a corda.fonte
Isso pode ser feito facilmente como
fonte
A maneira mais mnemônica de representar seu pseudo-código no Python seria:
fonte
if any(v >= 42 for v in (x, y, z)):
). E o desempenho de todos os 3 métodos (2 in {x,y,z}
,2 in (x,y,z)
,any(_v == 2 for _v in (x,y,z))
) parece ser quase o mesmo em CPython3.6 (veja Gist )Para testar várias variáveis com um único valor:
if 1 in {a,b,c}:
Para testar vários valores com uma variável:
if a in {1, 2, 3}:
fonte
Parece que você está construindo algum tipo de cifra de César.
Uma abordagem muito mais generalizada é a seguinte:
saídas
Não tenho certeza se é um efeito colateral desejado do seu código, mas a ordem da sua saída será sempre classificada.
Se é isso que você deseja, a linha final pode ser alterada para:
fonte
Você pode usar o dicionário:
fonte
Sem dict, tente esta solução:
e dá:
fonte
Isso irá ajudá-lo.
fonte
Você pode unir isso
em uma variável.
Altere nossas condições como:
Resultado:
fonte
Problema
Enquanto o padrão para testar vários valores
é muito legível e está funcionando em muitas situações, há uma armadilha:
Mas nós queremos ter
Solução
Uma generalização da expressão anterior é baseada na resposta de ytpillai :
que pode ser escrito como
Embora essa expressão retorne o resultado correto, ela não é tão legível quanto a primeira expressão :-(
fonte