Próbuję stworzyć funkcję, która porówna wiele zmiennych do liczby całkowitej i wyśle ciąg trzech liter. Zastanawiałem się, czy istnieje sposób na przetłumaczenie tego na Python. Powiedz więc:
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")
co zwróci listę:
["c", "d", "f"]
Czy coś takiego jest możliwe?
python
if-statement
comparison
match
boolean-logic
użytkownik1877442
źródło
źródło
1
in (krotka)any
/all
funkcji. Na przykład:all([1, 2, 3, 4, False])
zwróci Fałszall([True, 1, 2, 3])
zwróci Prawdaany([False, 0, 0, False])
zwróci Fałszany([False, 0, True, False])
zwróci Prawdaif x == 0 or 1:
, co oczywiście jest podobneif x or y == 0:
, ale może być nieco mylące dla początkujących. Biorąc pod uwagę czysty tom „Dlaczego mojax == 0 or 1
praca nie działa?” pytań, wolałbym raczej użyć tego pytania jako naszego kanonicznego duplikatu tych pytań.0
,0.0
lubFalse
. Możesz łatwo napisać zły kod, który daje „właściwą” odpowiedź.Odpowiedzi:
Nie rozumiesz, jak działają wyrażenia logiczne; nie działają jak angielskie zdanie i domyślają się, że mówisz o tym samym porównaniu dla wszystkich nazw tutaj. Szukasz:
x
iy
są inaczej oceniane na własną rękę (False
jeśli0
,True
inaczej).Możesz to skrócić za pomocą testu powstrzymywania krotki :
lub jeszcze lepiej:
używając a,
set
aby skorzystać z testu członkostwa o stałych kosztach (in
zajmuje to określoną ilość czasu bez względu na operand po lewej stronie).Gdy używasz
or
, python widzi każdą stronę operatora jako osobne wyrażenie. Wyrażeniex or y == 1
jest traktowane jako najpierw test boolowskix
, a następnie, jeśli jest to Fałsz, wyrażeniey == 1
jest testowane.Wynika to z pierwszeństwa operatora .
or
Operator ma niższy priorytet niż==
testu więc jest ona oceniana pierwszy .Jednak nawet gdyby tak nie było, a wyrażenie
x or y or z == 1
zostało zinterpretowane w(x or y or z) == 1
ten sposób, zamiast tego nadal nie działałoby zgodnie z oczekiwaniami.x or y or z
ocenia pierwszy argument, który jest „prawdziwy”, np. nieFalse
, 0 lub pusty (zobacz wyrażenia logiczne, aby uzyskać szczegółowe informacje na temat tego, co Python uważa za fałszywy w kontekście boolowskim).Więc dla wartości
x = 2; y = 1; z = 0
,x or y or z
rozwiąże się2
, ponieważ jest to pierwszy prawdziwy podobną wartość w argumentach. Wtedy2 == 1
byłobyFalse
, chociaży == 1
byłobyTrue
.To samo dotyczyłoby odwrotności; testowanie wielu wartości względem jednej zmiennej;
x == 1 or 2 or 3
zawiedzie z tych samych powodów. Użyjx == 1 or x == 2 or x == 3
lubx in {1, 2, 3}
.źródło
set
wersję. Krotki są bardzo tanie w tworzeniu i powtarzaniu. Na mojej maszynie krotki są szybsze niż zestawy, o ile rozmiar krotki wynosi około 4-8 elementów. Jeśli musisz zeskanować więcej, użyj zestawu, ale jeśli szukasz przedmiotu z 2-4 możliwości, krotka jest jeszcze szybsza! Jeśli można zorganizować najbardziej prawdopodobnym przypadku być pierwszym w krotce, wygrana jest jeszcze większa: (moje testy:timeit.timeit('0 in {seq}'.format(seq=tuple(range(9, -1, -1))))
)set
notacji literalnej w tym teście nie stanowi oszczędności, chyba że zawartośćset
literału jest również literalna, prawda?if 1 in {x, y, z}:
Nie można buforowaćset
, ponieważx
,y
iz
może się zmienić, więc albo potrzeby rozwiązanie do budowytuple
lubset
od podstaw, i podejrzewam, że cokolwiek odnośnika oszczędności można uzyskać podczas sprawdzania członkostwa będzie zapchana przez większyset
czas tworzenia.in [...]
czyin {...}
) działa tylko wtedy, gdy zawartość listy lub zestawu jest również niezmiennymi literałami.Twój problem można łatwiej rozwiązać za pomocą struktury słownika, takiej jak:
źródło
d = "cdef"
co prowadzi doMyList = ["cdef"[k] for k in [x, y, z]]
map(lambda i: 'cdef'[i], [x, y, z])
[x, y, z]
Jak stwierdził Martijn Pieters, poprawny i najszybszy format to:
Korzystając z jego rad, będziesz teraz mieć osobne instrukcje if, aby Python odczytał każdą instrukcję, niezależnie od tego, czy były to pierwsze,
True
czyFalse
. Jak na przykład:To zadziała, ale jeśli nie masz nic przeciwko korzystaniu ze słowników (zobacz, co tam zrobiłem), możesz to wyczyścić, tworząc początkowy słownik odwzorowujący liczby na pożądane litery, a następnie używając pętli for:
źródło
Bezpośrednim sposobem pisania
x or y or z == 0
jestAle nie sądzę, że ci się podoba. :) A ta droga jest brzydka.
Drugi sposób (lepszy) to:
BTW wiele
if
s można zapisać jako coś takiegoźródło
dict
zamiast klucza będziesz otrzymywać błędy, ponieważ zwracaną wartością.append
jestNone
, a wywołanieNone
dajeAttributeError
. Ogólnie jednak zgadzam się z tą metodą.filter
byłoby lepiej niżmap
, ponieważ zwróci tylko te przypadki, w których lambda ocenia się jako prawdaany(v == 0 for v in (x, y, z))
Jeśli jesteś bardzo leniwy, możesz umieścić wartości w tablicy. Jak na przykład
Możesz także wstawić cyfry i litery do słownika i zrobić to, ale jest to prawdopodobnie dużo bardziej skomplikowane niż zwykłe instrukcje. Właśnie to dostajesz za próbę bycia wyjątkowo leniwym :)
Jeszcze jedno, twoje
będzie się kompilować, ale nie w sposób, w jaki chcesz. Gdy po prostu wstawisz zmienną do instrukcji if (przykład)
program sprawdzi, czy zmienna nie ma wartości null. Innym sposobem napisania powyższej instrukcji (co ma większy sens) jest
Bool to wbudowana funkcja w pythonie, która w zasadzie wykonuje polecenie weryfikacji instrukcji boolowskiej (jeśli nie wiesz, co to jest, właśnie to próbujesz wykonać w instrukcji if :))
Znalazłem inny leniwy sposób:
źródło
list
jest wbudowanym Pythonem; zamiast tego użyj innej nazwy,xyz
na przykład. Dlaczego konstruujesz listę w czterech krokach, kiedy możesz to zrobić, tj.xyz = [x, y, z]
? Nie używaj list równoległych, zamiast tego użyj dykta. Podsumowując, to rozwiązanie jest znacznie bardziej skomplikowane niż rozwiązanie ThatGuyRussell . Także w ostatniej części, dlaczego nie zrobić zrozumienia, tj.any(v == 0 for v in (x, y, z))
? Również tablice są czymś innym w Pythonie.Aby sprawdzić, czy wartość jest zawarta w zestawie zmiennych, możesz użyć wbudowanych modułów
itertools
ioperator
.Na przykład:
Import:
Deklaruj zmienne:
Utwórz mapowanie wartości (w kolejności, którą chcesz sprawdzić):
Użyj,
itertools
aby umożliwić powtórzenie zmiennych:Na koniec użyj
map
funkcji, aby utworzyć iterator:Następnie, sprawdzając wartości (w oryginalnej kolejności), użyj
next()
:itp...
Ma to przewagę nad,
lambda x: x in (variables)
ponieważoperator
jest wbudowanym modułem i jest szybsze i bardziej wydajne niż używanielambda
które musi tworzyć niestandardowe funkcje na miejscu.Inna opcja sprawdzania, czy na liście jest niezerowa (lub Fałsz) wartość:
Odpowiednik:
źródło
Set jest tutaj dobrym podejściem, ponieważ porządkuje zmienne, co wydaje się twoim celem tutaj.
{z,y,x}
jest{0,1,3}
niezależnie od kolejności parametrów.W ten sposób całe rozwiązanie to O (n).
źródło
Wszystkie podane tutaj doskonałe odpowiedzi koncentrują się na specyficznych wymaganiach oryginalnego plakatu i koncentrują się na
if 1 in {x,y,z}
rozwiązaniu zaproponowanym przez Martijn Pieters.To, co ignorują, to szersza implikacja pytania:
jak przetestować jedną zmienną pod kątem wielu wartości?
Podane rozwiązanie nie będzie działać w przypadku częściowych trafień, jeśli na przykład użyjesz ciągów znaków:
Sprawdź, czy ciąg „Wild” ma wiele wartości
lub
w tym scenariuszu najłatwiej jest przekonwertować na ciąg
Należy jednak zauważyć, jak wspomniano przez
@codeforester
, że granice słów są tracone za pomocą tej metody, jak w:3 litery
rot
istnieją w połączeniu na liście, ale nie jako pojedyncze słowo. Testowanie na „zgniliznę” nie powiodło się, ale jeśli jeden z elementów listy byłby „zgnilizny w piekle”, również to by się nie powiodło.W związku z tym, jeśli używasz tej metody, uważaj na kryteria wyszukiwania i pamiętaj, że ma to ograniczenie.
źródło
Myślę, że to poradzi sobie lepiej:
Wynik:
źródło
Jeśli chcesz użyć if, w innym przypadku poniższe rozwiązanie jest innym rozwiązaniem:
źródło
źródło
Ten kod może być pomocny
źródło
Możesz wypróbować metodę pokazaną poniżej. W tej metodzie będziesz mieć swobodę określania / wprowadzania liczby zmiennych, które chcesz wprowadzić.
źródło
Rozwiązanie jednoliniowe:
Lub:
źródło
Może potrzebujesz bezpośredniej formuły dla zestawu bitów wyjściowych.
Mapujmy na bity:
'c':1 'd':0xb10 'e':0xb100 'f':0xb1000
Relacja isc (jest „c”):
Użyj matematyki, jeśli formuła https://youtu.be/KAdKCgBGK0k?list=PLnI9xbPdZUAmUL8htSl6vToPQRRN3hhFp&t=315
[do]:
(xyz=0 and isc=1) or (((xyz=0 and isc=1) or (isc=0)) and (isc=0))
[re]:
((x-1)(y-1)(z-1)=0 and isc=2) or (((xyz=0 and isd=2) or (isc=0)) and (isc=0))
...
Połącz te formuły według następującej logiki:
and
jest sumą kwadratów równańor
jest iloczynem równańa otrzymasz sumę równania wyrażoną sumą i masz całkowitą formułę sumy
następnie suma i 1 to c, suma i 2 to d, suma i 4 to e, suma i 5 to f
Następnie możesz utworzyć predefiniowaną tablicę, w której indeks elementów łańcucha odpowiadałby gotowemu łańcuchowi.
array[sum]
daje ci ciąg.źródło
Można to łatwo zrobić jako
źródło
Najbardziej mnemonicznym sposobem reprezentowania twojego pseudokodu w Pythonie byłoby:
źródło
if any(v >= 42 for v in (x, y, z)):
.). I wydajność wszystkich 3 metod (2 in {x,y,z}
,2 in (x,y,z)
,any(_v == 2 for _v in (x,y,z))
) wydaje się być prawie takie same w CPython3.6 (patrz GIST )Aby przetestować wiele zmiennych za pomocą jednej wartości:
if 1 in {a,b,c}:
Aby przetestować wiele wartości za pomocą jednej zmiennej:
if a in {1, 2, 3}:
źródło
Wygląda na to, że budujesz jakiś szyfr Cezara.
O wiele bardziej ogólne podejście to:
wyjścia
Nie jestem pewien, czy jest to pożądany efekt uboczny kodu, ale kolejność wyników zawsze będzie sortowana.
Jeśli tego właśnie chcesz, ostatnią linię można zmienić na:
źródło
Możesz użyć słownika:
źródło
Bez dyktowania wypróbuj to rozwiązanie:
i daje:
źródło
To ci pomoże.
źródło
Możesz to zjednoczyć
w jednej zmiennej.
Zmień nasze warunki jako:
Wynik:
źródło
Problem
Podczas gdy wzorzec do testowania wielu wartości
jest bardzo czytelny i działa w wielu sytuacjach, istnieje jedna pułapka:
Ale my chcemy mieć
Rozwiązanie
Jedno uogólnienie poprzedniego wyrażenia opiera się na odpowiedzi z ytpillai :
które można zapisać jako
Chociaż to wyrażenie zwraca właściwy wynik, nie jest tak czytelne jak pierwsze wyrażenie :-(
źródło