Czy istnieje lepszy sposób pisania v = (v == 0? 1: 0); [Zamknięte]


465

Chcę przełączać zmienną między 0 a 1. Jeśli jest to 0, chcę ustawić ją na 1, w przeciwnym razie, jeśli jest to 1, chcę ją ustawić na 0.

Jest to tak fundamentalna operacja, że ​​tak często piszę, chciałbym zbadać najkrótszy, najczystszy możliwy sposób. Oto moje najlepsze jak dotąd:

v = (v == 0 ? 1 : 0);

Czy możesz to poprawić?

Edycja: pytanie dotyczy tego, jak napisać powyższe stwierdzenie przy użyciu jak najmniejszej liczby znaków, zachowując jasność - dlaczego to „nie jest prawdziwe pytanie”? To nie miało być ćwiczenie w golfa kodowego, chociaż pojawiły się interesujące odpowiedzi od ludzi, którzy podchodzą do niego jako golfa - miło jest widzieć, że golf jest wykorzystywany w konstruktywny i pobudzający do myślenia sposób.


20
Dla mnie to wygląda już na proste / jasne / krótkie.
Mob

136
oszustwo:v = +!v;
jAndy

48
Jeśli „lepszy” oznacza również „szybszy”: jsperf.com/v-0-1-0 .
pimvdb,

7
@Mobinga: +1. To jest tak proste, jak powinno być. Wszystkie pozostałe odpowiedzi, które widzę, są mylące, a niektóre z nich zmieniają logikę; wprowadzanie błędów.
Ian Boyd

8
@holodoc Lepszym rozwiązaniem do wyrażenia swojej opinii byłoby stworzenie odpowiedzi, która mówi, że uważasz, że oryginał jest najlepszym sposobem, i rozwinięcie, dlaczego uważasz, że tak jest. pozwala to również innym osobom łatwo poprzeć twoją odpowiedź, głosując ją w górę.
Chuck van der Linden

Odpowiedzi:


721

Możesz po prostu użyć:

v = 1 - v;

Zakłada to oczywiście, że zmienna została poprawnie zainicjowana, tzn. Że ma tylko wartość 0 lub 1.

Inna metoda, która jest krótsza, ale używa mniej popularnego operatora:

v ^= 1;

Edytować:

Dla jasności; Nigdy nie podchodziłem do tego pytania jako do gry w golfa kodowego, tylko po to, aby znaleźć sposób na wykonanie zadania bez korzystania z niejasnych sztuczek, takich jak skutki uboczne operatorów.


206
Są to piękne linie kodu, takie jak drobno cięte szkło lub rzadkie kwitnące storczyki. Uwielbiam to, jak osiągnąłeś warstwę logiczną i poradziłeś sobie bezpośrednio z matematyką 1 i 0 przy najbardziej optymalnych operacjach. Będę ich używał we własnych projektach, ale niestety, kiedy będę potrzebować kodu do zrozumienia przez współpracowników, będę musiał przejść na podejście bardziej logiczne. Dziękuję jednak, twoja odpowiedź sprawiła, że ​​mój dzień.
Ollie Glass

37
Zawsze możesz dodać komentarz mówiący o tym, co robi kod.
Prusse

25
@Kevin: to nieprawda, że ​​to wyraźnie nie odpowiada na zadane pytanie. Q powiedział „Chcę przełączać zmienną pomiędzy 0 a 1.” Bardzo rozsądną interpretacją jest to, że implikuje to, że wartość zmiennej wynosi już 0 lub 1. Ta interpretacja / ograniczenie zostało wyraźnie określone w odpowiedzi. Co, na świecie, możesz się sprzeciwić?
LarsH

50
@ Mateusz, aby powiedzieć, że ktoś, kto nie jest v ^= 1jasny, powinien przestać programować, jest to trochę trudne. Jak już wspomniano, nie jest to jeden z bardziej popularnych operatorów i nie robi tego samego, co v = v ^ 1. Również operator oznacza coś zupełnie innego w różnych językach (VB). Tak, szybkie sprawdzenie pokaże, że jest to operator XOR i zrozumiesz, co robi, ale dla wielu może to nie być oczywiste na pierwszy rzut oka. Nie sądzę, że to oznacza, że ​​musisz rzucić pracę.
JD Isaacks

80
Jeśli zapiszesz 15 znaków, pisząc to, ale następnie wykorzystasz 40 znaków komentarza, aby to wyjaśnić, czy to naprawdę poprawa?
Michael Myers

343

Ponieważ 0jest falsewartością i 1jest truewartością.

v = (v ? 0 : 1);

Jeśli jesteś szczęśliwy w użyciu truei falsezamiast liczb

v = !v;

lub jeśli muszą to być liczby:

v = +!v; /* Boolean invert v then cast back to a Number */

55
po prostu włóż magię +wcześniej !. Och, to wygląda na takie brudne! ale fajnie: p
jAndy

1
@Quentin - to złamie kod faceta, jeśli on ma switch(v){ case 0 ...lub jeśli (v == 0) lub jeśli v === 0. Zmieniasz jego wynik oprócz jego podejścia ....
Brian

34
Zrób buźkę z nim: ({v :+! v}).v.
pimvdb,

17
@Brian: nie z tym magicznym +znakiem! ¯ \ _ (ツ) _ / ¯
jAndy

11
+1 za v = (v ? 0 : 1)tak czysty i idiomatyczny JS.
Bennett McElwee

200

v = (v + 1) % 2a jeśli potrzebujesz przechodzić przez kolejne wartości, po prostu zmień 2dla (n + 1). Powiedz, że musisz zrobić cykl 0,1,2 po prostu zrób v = (v + 1) % 3.


2
Uwielbiam ten cykl! To naprawdę sprytne.
Ollie Glass

16
+1 za myślenie o przełączeniu jako cyklu. Proste, biorąc pod uwagę jego elastyczność.
Guffa

3
+1 za zapewnienie solidnego rozwiązania modułowego. W praktyce prawdopodobnie będziesz chciał użyć constzmiennej zamiast magicznych liczb 2, 3, ...
oosterwal

2
Krótszy (trudniejszy) sposób: ++v % 3jeśli chcesz jeździć przez 0, 1, 2
haraldmartin

75

Możesz napisać dla niego funkcję i używać jej w następujący sposób:

v = inv(v)


30
+1 Zdecydowanie zgadzam się, że jest to najczystsze rozwiązanie (... ale co się dzieje w invfunkcji: P)
Lea Hayes

4
Chciałbym dać tę odpowiedź więcej niż +1. Jeśli wspólny kod nie jest oślepiająco oczywisty, powinien zostać zawinięty w funkcję o nazwie opisowej.
TehShrike,

11
@TehShrike czy uważasz, invże to opisowa nazwa?
Bennett McElwee

3
@Bennett McElwee: inv = invert. Zawsze wydawało mi się to zwykłym skrótem.
Daniel

51
Po co więc go skracać, nazywać go „odwracaniem” lub „przełączać”, aby kod był czytelny. to nie tak, że próbujemy dopasować te rzeczy do 80-kolumnowej karty dziurkacza lub czegoś takiego.
Chuck van der Linden

50

Jeśli nie obchodzi Cię żadna inna możliwość niż 1:

v = v ? 0 : 1;

W powyższym przypadku v skończy się na 1, jeśli v wynosi 0, false, niezdefiniowany lub null. Zachowaj ostrożność stosując takie podejście - v będzie wynosić 0, nawet jeśli v to „witaj świecie”.


2
To nie zmieni wartości. Masz na myśli v = v ? 0 : 1.
Guffa

3
@Guffa - +1 za złapanie mojej dysleksji ...
Brian

3
To jest moja ulubiona odpowiedź oparta na logice, której mogę używać u współpracowników (widzę odpowiedź @ Guffa jako liczbową). Podoba mi się sposób, w jaki przeprowadziłeś niepotrzebny test (v == 0) i nawias kwadratowy, zmniejszając go do absolutnej minimalnej liczby znaków. Dziękuję Ci.
Ollie Glass

1
Jestem też wielkim fanem odpowiedzi @ Guffa - słowami Lynard Skynard, nie krępuj się;)
Brian

2
+1 za zrozumienie „prawdziwych” wartości.
zzzzBov

44

Linie podoba v = 1 - v, albo v ^= 1czy v= +!vbędzie wszystko to zadanie, ale stanowią one co ja określam jako hacki. Nie są to piękne linie kodu, ale tanie sztuczki, które mają przynieść zamierzony efekt. 1 - vnie komunikuje się „przełącza wartość między 0 a 1”. To sprawia, że ​​Twój kod jest mniej wyrazisty i wprowadza miejsce (choć małe), w którym inny programista będzie musiał przeanalizować Twój kod.

Posiadanie zamiast tego funkcji podobnej do v = toggle(v)komunikuje intencję na pierwszy rzut oka.


8
-1, na poważnie, v=1-vnie komunikuje przełączania?
Blindy,

22
1-vpotrafi się naprawdę przełączać, ale to jedyna rzecz, którą się komunikuje. Na przykład może również komunikować linię o wartości zero w v=1lub transformację odbicia lustrzanego na środku v=0.5. W tym sensie jest to względnie niejednoznaczne. Prawdą jest, że wiedza o tym, że zawsze vmoże być 0lub 1ogranicza jego zamierzone znaczenie, ale zmusza innych programistów (lub twoje przyszłe ja) do zrozumienia tego kontekstu, zanim będzie w stanie zrozumieć tę prostą linię. Nie możesz być dużo jaśniejszy niżv = toggle(v)
Ray

10
v ^= 1jest całkowicie jasne, jeśli rozumiesz operacje logiczne, które lepiej mieć, jeśli jesteś programistą. Myślę, że to różnica między tym a v=1-v; jedna jest operacją logiczną, a druga operacją arytmetyczną, a my próbujemy przedstawić koncepcję logiczną, a nie matematyczną.
Mateusz

6
@Matthew Read: To wspaniałe stwierdzenie, które dobrze podsumowuje moje myśli: „staramy się przedstawić logiczną koncepcję, a nie matematykę”. v ^= 1Ma nawet pewną dwuznaczność, ponieważ można go interpretować jako xor.
Ray

6
dla programistów (i tak, mam na myśli maniaków takich jak my), są one dość jasne. Nie są hackami, ponieważ są eleganckimi rozwiązaniami ze względu na swoją prostotę.
gion_13,

38

( Uczciwość i integralność matematyczna - biorąc pod uwagę liczbę głosów na tę „odpowiedź” - skłoniły mnie do zredagowania tej odpowiedzi. Wstrzymałem się tak długo, jak to możliwe, ponieważ miała ona służyć jako krótki żart, a nie jakkolwiek „głęboka” wszelkie wyjaśnienia wydawały się sprzeczne z celem. Jednak komentarze wyjaśniają, że powinienem być jasny, aby uniknąć nieporozumień ).

Moja oryginalna odpowiedź:

Treść tej części specyfikacji:

Jeśli wynosi 0, chcę ustawić go na 1, w przeciwnym razie ustaw go na 0.

oznacza, że ​​najdokładniejszym rozwiązaniem jest:

v = dirac_delta(0,v)

Po pierwsze, wyznanie: I nie dostać moje funkcje delta mylić. Delta Kroneckera byłaby nieco bardziej odpowiednia, ale nie tak bardzo, jak chciałem czegoś niezależnego od domeny (delta Kroneckera jest używana głównie dla liczb całkowitych). Ale tak naprawdę nie powinienem był w ogóle używać funkcji delta, powinienem powiedzieć:

v = characteristic_function({0},v)

Pozwól mi wyjaśnić. Przypomnijmy, że funkcja jest potrójne, (X, Y, F) , gdzie X i Y są zestawy (zwanej domeną i codomain r) i f jest to regułą, że wyznacza pewien element Y każdego elementu X . Często napisać potrójne (X, Y, F) jako f: X → Y . Biorąc pod uwagę podzbiór X , powiedzmy A , istnieje funkcja charakterystyczna, która jest funkcją χ A : X → {0,1}(można to również traktować jako funkcję większej kodomainy, takiej jak ℕ lub ℝ). Ta funkcja jest zdefiniowana przez regułę:

χ (x) = 1 jeśli x ∈ A i χ (x) = 0 , jeżeli x ∉ .

Jeśli podoba Ci się tablica prawdy, to tabela prawda na pytanie „Czy element x od X elementem podzbioru A ?”.

Zatem z tej definicji jasno wynika, że ​​potrzebna jest tutaj funkcja charakterystyczna, z X jakimś dużym zestawem zawierającym 0 i A = {0} . Tak powinienem był napisać.

I tak do funkcji delta. W tym celu musimy wiedzieć o integracji. Albo już to wiesz, albo nie. Jeśli nie, nic, co mogę tu powiedzieć, nie mówi o zawiłościach teorii, ale mogę streścić jedno zdanie. Środek na zbiorze X jest w istocie „to, co jest potrzebne, aby oglądalność pracę”. To znaczy, że jeśli mamy zbiór X i miarę μ na tym zbiorze, to istnieje klasa funkcji X → ℝ , zwanych funkcjami mierzalnymi, dla których wyrażenie X f dμ ma sens i jest, w pewnym sensie niejasnym, „średni” z f nad X .

Biorąc pod uwagę miarę na zestawie, można zdefiniować „miarę” dla podzbiorów tego zestawu. Odbywa się to poprzez przypisanie do podzbioru całki jego funkcji charakterystycznej (przy założeniu, że jest to funkcja mierzalna). Może to być nieskończone lub niezdefiniowane (oba są subtelnie różne).

Wokół jest wiele środków, ale tutaj są dwa ważne. Jednym z nich jest standardowa miara na linii rzeczywistej ℝ. W tym przypadku f dμ jest właściwie tym, czego uczysz się w szkole (czy rachunek wciąż jest nauczany w szkołach?): Zsumuj małe prostokąty i przyjmuj coraz mniejsze szerokości. W tej mierze miarą przedziału jest jego szerokość. Miara punktu wynosi 0.

Inną ważną miarą, która działa na dowolnym zestawie, jest tak zwana miara punktowa . Jest on zdefiniowany w taki sposób, że całka funkcji jest sumą jej wartości:

X f dμ = ∑ x ∈X f (x)

Ta miara przypisuje do każdego zestawu singletonów miarę 1. Oznacza to, że podzbiór ma miarę skończoną wtedy i tylko wtedy, gdy sam jest skończony. I bardzo niewiele funkcji ma całkę skończoną. Jeśli funkcja ma całkę skończoną, musi być niezerowa tylko na policzalnej liczbie punktów. Tak więc ogromna większość funkcji, które prawdopodobnie znasz, nie ma skończonej całki w ramach tej miary.

A teraz funkcje delta. Weźmy bardzo szeroką definicję. Mamy wymierną przestrzeń (X, μ) (tak, to zestaw z miarą na nim) i element a ∈ X . „Definiujemy” funkcję delta (w zależności od a ), aby była „funkcją” δ a : X → ℝ z właściwością, że δ a (x) = 0, jeśli x ≠ a i X δ a dμ = 1 .

Najważniejszym faktem, który należy wziąć pod uwagę, jest to: funkcja delta nie musi być funkcją . To jest nie poprawnie zdefiniowane: Nie powiedziałem co Æ (a) jest.

To, co robisz w tym momencie, zależy od tego, kim jesteś. Świat tutaj dzieli się na dwie kategorie. Jeśli jesteś matematykiem, mówisz:

Okej, więc funkcja delta może nie zostać zdefiniowana. Spójrzmy na jego hipotetyczne właściwości i zobaczmy, czy możemy znaleźć dla niego odpowiedni dom, w którym jest zdefiniowany. Możemy to zrobić i skończymy z dystrybucjami . Nie są to (koniecznie) funkcje, ale rzeczy, które zachowują się trochę jak funkcje i często możemy z nimi pracować tak, jakby były funkcjami; ale są pewne rzeczy, których nie mają (takie jak „wartości”), dlatego musimy być ostrożni.

Jeśli nie jesteś matematykiem, powiedz:

Okej, więc funkcja delta może nie być poprawnie zdefiniowana. Kto tak mówi? Grono matematyków? Ignoruj ​​ich! Co oni wiedzą

Obrażając teraz moją publiczność, będę kontynuować.

Diraca delta zazwyczaj przyjmuje się, że funkcja delta punktu (często 0) w prostej ze standardowego środka. Więc ci, którzy narzekają w komentarzach na mój temat, nie znając moich delt, robią to, ponieważ używają tej definicji. Przepraszam: chociaż mogę się z tego wywinąć, korzystając z obrony Matematyka (spopularyzowanej przez Humpty'ego Dumpty'ego : po prostu przedefiniuj wszystko, aby było poprawne), ale złym sposobem jest użycie standardowego terminu na oznaczenie czegoś innego.

Ale jest funkcja delta, która robi to, co chcę, i jest to, czego potrzebuję tutaj. Jeśli biorę środka punkt w zbiorze X to nie jest prawdziwym funkcja δ a : X → ℝ , która spełnia kryteria dla funkcji delta. Wynika to z faktu, że szukamy funkcji X → ℝ, która jest równa zero, z wyjątkiem a i takiej, że suma wszystkich jej wartości wynosi 1. Taka funkcja jest prosta: jedyną brakującą informacją jest jej wartość przy a , i aby otrzymać sumę równą 1, po prostu przypisujemy jej wartość 1. Jest to nic innego jak funkcja charakterystyczna na {a} . Następnie:

X δ a dμ = ∑ x ∈ X δ a (x) = δ a (a) = 1.

Tak więc w tym przypadku dla zestawu singletonowego funkcja charakterystyczna i funkcja delta są zgodne.

Podsumowując, istnieją tutaj trzy rodziny „funkcji”:

  1. Charakterystyczne funkcje zbiorów singletonów,
  2. Funkcje delta,
  3. Funkcje delty Kroneckera.

Drugi z nich jest najbardziej ogólnym, jak każdy z pozostałych jest przykładem nim przy użyciu środka punktową. Ale pierwsza i trzecia mają tę zaletę, że są to zawsze oryginalne funkcje. Trzeci jest w rzeczywistości szczególnym przypadkiem pierwszego, dla konkretnej rodziny domen (liczb całkowitych lub niektórych ich podzbiorów).

Wreszcie, kiedy pierwotnie napisałem odpowiedź, nie myślałem poprawnie (nie posunąłem się nawet do stwierdzenia, że ​​byłem zdezorientowany , ponieważ mam nadzieję, że właśnie pokazałem, że wiem o czym mówię, kiedy Właściwie to najpierw myślę, po prostu niewiele myślałem). Zwykłe znaczenie delty diraca nie jest tutaj potrzebne, ale jednym z punktów mojej odpowiedzi było to, że domena wejściowa nie została zdefiniowana, więc delta Kroneckera również nie miałaby racji. Zatem najlepszą odpowiedzią matematyczną (do której dążyłem) byłaby funkcja charakterystyczna .

Mam nadzieję, że to wszystko jasne; i mam również nadzieję, że już nigdy nie będę musiał pisać matematyki używając encji HTML zamiast makr TeX!


37
+1 - Gdybym mógł oddać głos Quentinowi za nieznajomość funkcji dirac_delta, zrobiłbym to. Chciałbym wiedzieć, do którego college'u poszedł, ponieważ nie sądzę, żebym zatrudnił kogoś z tego miejsca, gdyby nawet nie wiedział czegoś tak fundamentalnego dla przetwarzania cyfrowego. Chciałbym jeszcze bardziej zlekceważyć Quentina za jego niezdolność uchwycenia odrobiny humoru, którą próbujesz.
Dunk

23
Gdybym zanegował każdą odpowiedź, której nie rozumiałem ... Głosowałbym za wieloma odpowiedziami.
Seamus

4
Cześć Andrew, minęło trochę czasu.
Tim Down

4
@Tim: Dobry smutek, więc ma! A jak się ma biskup Bermudów? (Czy pamiętam, że tak?) Myślę, że ten komentarz nie jest najlepszym miejscem do nadrobienia zaległości, choć ... 17 lat, prawda?
Andrew Stacey,

3
@ Cԃ ա ԃ "Ta odpowiedź nie powiodło się ..." westchnienie . Czytałeś, że jestem matematykiem, prawda? Ta odpowiedź działa idealnie dla programisty sferycznego w próżni, więc nie wiem, na co narzekasz.
Andrew Stacey,

35

Mógłbyś

v = Math.abs(--v);

Zmniejszenie ustawia wartość na 0 lub -1, a następnie Math.abskonwertuje -1 na +1.


27
Zmieniło się to w konkurs „Generuj 10000 sposobów na proste zadanie”. I lubię wszystkie sposoby, haha.
Josh

27
v = Math.round(Math.sin(Math.PI/(v+3)));
Benoit

15
@Benoit - twoja formuła wynosi 1 zarówno dla v = 0, jak i v = 1. Ten jest jednak poprawny! v = Math.round(Math.cos(Math.PI/((v*2+1)+2)-2*v));: D
Teo.sk

2
To nigdy nie zmieni wartości. Jeśli v = 1to, v = Math.Abs(-1)co jest +1. Jeśli v = 0więc v = Math.Abs(-0)to jest 0.
Paweł

1
+1 A to był mój drugi ... Grr.
rekurencyjny

34

ogólnie za każdym razem, gdy trzeba przełączać się między dwiema wartościami, można po prostu odjąć bieżącą wartość od sumy dwóch wartości przełączania:

    0,1 -> v = 1 - v
    1,2 -> v = 3 - v
    4,5 -> v = 9 - v 

2
Jest to interesujące i kreatywne, ale potencjalnie niebezpieczne. Jeśli vzostanie uszkodzony, nagle zacznie się przełączać między dwiema różnymi wartościami. (Tylko coś do rozważenia ...)
oosterwal

1
+1 za ciekawy pomysł. nie dlatego, że OP lub ktokolwiek inny użyje go w takich okolicznościach, ale ta informacja powinna istnieć gdzieś w mózgu na zawsze.
Shimmy Weitzhandler,

3
@ oosterwal: Zatem z pewnością problem leży w korupcji ...
GManNickG

@GManNickG: Wcześniej czy później nastąpi uszkodzenie danych, więc musimy zdawać sobie sprawę z konsekwencji niewykrycia tego. Jeśli vnormalnie jest używany do naprzemiennego wykonywania dwóch stanów z listy trzech lub więcej stanów, wówczas uszkodzenie vmoże spowodować naprzemienne wykonywanie przez program dwóch zupełnie różnych stanów - może to spowodować nieoczekiwane i niepożądane wyniki. Lekcja, którą należy wyciągnąć z tego jest następująca: Zawsze sprawdzaj wiarygodność swoich danych.
oosterwal

33

Jeśli musi to być liczba całkowita 1 lub 0, to sposób, w jaki to robisz, jest w porządku, chociaż nawiasy nie są potrzebne. Jeśli te mają być używane jako booleany, możesz po prostu zrobić:

v = !v;

10
czy to nie spowoduje, że Ollie „v” zostanie ustawiony na wynik boolowski, a nie na liczbę całkowitą?
Brian

12
Tak, i ostrzegłem w zdaniu powyżej wiersza kodu. Jeśli te mają być użyte jako booleany
Michał Berkowski

23
v = v == 0 ? 1 : 0;

Wystarczy !


7
Więcej opinii niż odpowiedzi, nie sądzisz?
Brian

16
@Brian: „lepiej” to tak naprawdę opinia.
pimvdb,

3
Podoba mi się to, jak wyciągnąłeś nawiasy klamrowe - to przycina kilka znaków!
Ollie Glass

9
@Brian: „ Odpowiedź ” brzmi „Nie, nie ma lepszego sposobu pisania v = (v==0 ? 1 : 0); . Wszyscy inni znajdują różne sposoby gry w golfa; i nie odpowiadając na pytanie. Właśnie dlatego głosowałem za tą odpowiedzią.
Ian Boyd

19

Lista rozwiązań

Są trzy rozwiązania, które chciałbym zaproponować. Wszystkie z nich przekształcić dowolną wartość 0(jeśli 1, trueitd.) Lub 1(jeśli 0, false, nullitd.):

  • v = 1*!v
  • v = +!v
  • v = ~~!v

i jeden dodatkowy, już wspomniany, ale sprytny i szybki (chociaż działa tylko dla 0s i 1s):

  • v = 1-v

Rozwiązanie 1

Możesz użyć następującego rozwiązania:

v = 1*!v

To najpierw przekształci liczbę całkowitą na przeciwną wartość logiczną ( 0na Truei dowolną inną wartość na False), a następnie potraktuje ją jako liczbę całkowitą podczas mnożenia 1. W rezultacie 0zostaną przekonwertowane na 1dowolną inną wartość 0.

Jako dowód zobacz to jsfiddle i podaj wszelkie wartości, które chcesz przetestować: jsfiddle.net/rH3g5/

Wyniki są następujące:

  • -123zamieni się na liczbę całkowitą 0,
  • -10zamieni się na liczbę całkowitą 0,
  • -1zamieni się na liczbę całkowitą 0,
  • 0zamieni się na liczbę całkowitą 1,
  • 1zamieni się na liczbę całkowitą 0,
  • 2zamieni się na liczbę całkowitą 0,
  • 60zamieni się na liczbę całkowitą 0,

Rozwiązanie 2

Jak zauważył mblase75, jAndy miał inne rozwiązanie, które działa jak moje:

v = +!v

Najpierw robi też wartość logiczną z pierwotnej wartości, ale używa +zamiast 1*konwertować ją na liczbę całkowitą. Wynik jest dokładnie taki sam, ale notacja jest krótsza.

Rozwiązanie 3

Innym podejściem jest użycie ~~operatora:

v = ~~!v

Jest to dość rzadkie i zawsze zamienia się na liczbę całkowitą z wartości logicznej.


W JavaScript możesz poprzedzić zmienną, +aby przekonwertować ją na liczbę, więc +!vjest to odpowiednik twojego rozwiązania (rozwiązanie jAndy w komentarzach PO).
Blazemonger

@ mblase75: Tak, masz rację, którą 1*można zastąpić +przy próbie konwersji wartości logicznej na liczbę całkowitą. Wszystko inne w mojej odpowiedzi pozostaje takie samo. Odpowiedź Andy'ego jest poprawna, ale moja jest bardziej szczegółowa. Dodam jego / jej rozwiązanie do mojej odpowiedzi.
Tadeck

@ Tadeck +1 za fajny pomysł.
Shimmy Weitzhandler,

17

Podsumowując inną odpowiedź, komentarz i moją własną opinię, sugeruję połączenie dwóch rzeczy:

  1. Użyj funkcji do przełączania
  2. Wewnątrz tej funkcji użyj bardziej czytelnej implementacji

Oto funkcja, którą możesz umieścić w bibliotece lub zawinąć we wtyczkę dla innego środowiska JavaScript.

function inv(i) {
  if (i == 0) {
    return 1
  } else {
    return 0;
  }
}

A użycie jest po prostu:

v = inv(v);

Zalety to:

  1. Brak powielania kodu
  2. Jeśli ty lub ktokolwiek przeczytasz to w przyszłości, zrozumiesz swój kod w minimalnym czasie.

Czy oni są? Przeprowadziłem szybki test: jsperf.com/function-vs-no-function/2 i wydaje się, że różnica nie jest aż tak duża.
Martin Schlagnitweit,

25
7,5ns vs 8,8ns. Te dodatkowe 1,3 nanosekundy naprawdę cię zabiją.
Ian Boyd

5
Przez cały czas, który oszczędzałem, zabrałem swoją rodzinę do Disney World! :-)
Tom

1
Całkowicie poprawne. Ludzie piszący „sprytne” rozwiązania prawdopodobnie nigdy nie musieli utrzymywać innych programistów kodujących „klejnoty”
Avi

1
dlaczego nie function toggle(i){ return i == 0 ? 1 : 0 }?
Billy Moon,

13

Nie wiem, dlaczego chcesz budować własne booleany? Lubię funky składnie, ale dlaczego nie napisać zrozumiałego kodu?

To nie jest najkrótszy / najszybszy, ale najczystszy (i czytelny dla wszystkich) to znany stan if / else:

if (v === 0)
{
  v = 1;
}
else
{
  v = 0;
}

Jeśli chcesz być naprawdę jasny, powinieneś użyć do tego boolanów zamiast liczb. Są wystarczająco szybkie w większości przypadków. W przypadku booleanów możesz po prostu użyć tej składni, która wygra w skrócie:

v = !v;

1
To właściwie byłaby moja preferowana odpowiedź; ale potrójny operator kontra jeśli- to święta wojna, nie chciałem zapalić bezpiecznika. To powiedziawszy, myślę, że powinna być pierwsza linia === 0. Przy przykładowym wprowadzeniu 7poprawnego wyniku jest 0, ale to da wynik 1.
Ian Boyd,

4
Czy warto dyskretnie korygować dane wejściowe, takie jak 7, zamiast zgłaszać jakiś wyjątek? Chodzi mi o to, że jeśli jakiś inny kod dostanie 7, kiedy spodziewał się 0 lub 1, zanim Twój kod skoryguje wartość?
Chuck van der Linden

12

Inna forma Twojego oryginalnego rozwiązania:

v = Number(v == 0);

EDYCJA: Dzięki TehShrike i Guffa za wskazanie błędu w moim oryginalnym rozwiązaniu.


4
Operator == zwraca wartość logiczną (zamiast liczby całkowitej) w wielu systemach. Działałoby to tylko wtedy, gdy v zdefiniowano jako liczbę całkowitą, a język był fajny z automatycznym rzutowaniem z wartości logicznej na liczbę całkowitą.
TehShrike,

Bardzo prawdziwe. Odpowiedziałem na to pytanie w kontekście javascript (w jaki sposób pytanie zostało oznaczone).
Kurt Kaylor,

@Kurt Kaylor: Javascript jest jednym z systemów, w których operator == zwraca wartość logiczną, więc nie robi tego samego, co oryginalne rozwiązanie.
Guffa,

@Guffa: Korzystam z faktu, że javascript jest językiem słabo typowanym z niejawną konwersją typów (np. „0,0000” == 0, 0 == "", fałsz == "", fałsz == 0, 1 == prawda itp.). Mogę użyć zwróconej wartości logicznej w taki sam sposób, jak mogę użyć liczby całkowitej o wartości 0 lub 1. Spróbuj na przykład ocenić „2 + true” w konsoli javascript, otrzymasz 3.
Kurt Kaylor

1
@Kurt Kaylor: Działa to tylko w sytuacjach, gdy wymuszasz niejawną konwersję. Spróbuj na przykład, 'opacity:'+truea skończysz na opacity:truezamiast opacity:1.
Guffa,

11

Uściśliłbym to.

Co vznaczy

Na przykład, gdy v to jakiś stan. Utwórz status obiektu. W DDD obiekt wartości.

Zaimplementuj logikę w tym obiekcie wartości. Następnie możesz napisać kod w bardziej funkcjonalny sposób, który jest bardziej czytelny. Przełączanie statusu można wykonać, tworząc nowy status w oparciu o bieżący status. Twoja instrukcja / logika if jest następnie enkapsulowana w twoim obiekcie, co możesz zabronić. ValueObject jest zawsze niezmienny, więc nie ma tożsamości. Aby zmienić jego wartość, musisz stworzyć nową.

Przykład:

public class Status
{
    private readonly int _actualValue;
    public Status(int value)
    {
        _actualValue = value;
    }
    public Status(Status status)
    {
        _actualValue = status._actualValue == 0 ? 1 : 0; 
    }

    //some equals method to compare two Status objects
}

var status = new Status(0);

Status = new Status(status);

6
nad inżynierią?
alejandro5042,

6
+1 za rozśmieszenie mnie
Denshi,


10

Brakuje:

v = [1, 0][v];

Działa również jako okrągły robin:

v = [2, 0, 1][v]; // 0 2 1 0 ...
v = [1, 2, 0][v]; // 0 1 2 0 ...
v = [1, 2, 3, 4, 5, 0][v]; // 0 1 2 3 4 5 ...
v = [5, 0, 1, 2, 3, 4][v]; // 0 5 4 3 2 1 0 ...

Lub

v = {0: 1, 1: 0}[v];

Urok tego ostatniego rozwiązania, działa również ze wszystkimi innymi wartościami.

v = {777: 'seven', 'seven': 777}[v];

W bardzo szczególnym przypadku, na przykład w celu uzyskania (zmieniającej się) wartości undefined, ten wzorzec może być pomocny:

v = { undefined: someValue }[v]; // undefined someValue undefined someValue undefined ...

9

Ponieważ jest to JavaScript, możemy użyć unary +do konwersji na int:

v = +!v;

Będzie to logiczne NOTdla wartości v(podającej truejeśli v == 0lub falsejeśli v == 1). Następnie przekształcamy zwróconą wartość logiczną na odpowiadającą jej liczbę całkowitą.



7

Jeszcze jeden: v=++v%2

(w C byłoby to proste ++v%=2)

ps. Tak, wiem, że to podwójne przypisanie, ale to tylko surowe przepisanie metody C.


3
Twoja wersja C jest nielegalna; nie możesz modyfikować wyniku ++operatora (to nie jest wartość). Co do tego v=++v%2, modyfikujesz vdwa razy. Nie wiem, czy jest to dobrze zdefiniowane w JavaScript, ale nie jest to konieczne. v = (v+1) % 2.
Keith Thompson,

Przynajmniej w c++tym jest - ponieważ operator wstępnej inkrementacji ma wyższy priorytet i modyfikuje zmienną „na miejscu”, dzięki czemu może być używana jako wartość. Myślę, że implementacja JS ++jest taka, że ​​nie można jej traktować jak wartości: / Tak, to jest zbędne, ale starałem się pokazać tylko inną metodę - są już opublikowane lepsze rozwiązania :)
Adam Jurczyk

3
+1. Można zapisać jako v = (v + 1)% 2.
niktrs

7

Jeśli masz gwarancję, że twoja wartość to 1 lub 0, możesz użyć:

v = 2+~v;

7

zdefiniuj tablicę {1,0}, ustaw v na v [v], dlatego v o wartości 0 staje się 1 i vice versa.


Moje rozwiązanie jest poprawne, jeśli ci się nie podoba, napisz dlaczego. Twój komentarz nikomu nie pomaga. Moje rozwiązanie czyta zmienną, a nie podejmuje decyzję. Wymaga to mniej procesora.
S ..

5

Inny kreatywny sposób na zrobienie tego, z vrównością dowolnej wartości, zawsze powróci 0lub1

v = !!v^1;

3
dwa !!skutkują niczym w logice matematycznej, którą można !!!!tam umieścić i będą takie same, ale będą skutkować 4 niepotrzebnymi operacjami
Alex K

10
@Alex: !!rzuci na bool. !!(1) === trueoraz!!(0) === false
nickf

1
@nickf: aha, więc myślę v = Boolean(v^1), że byłby bardziej informacyjny, dzięki za wyjaśnienie - nie myślałem o castingu
Alex K

1
@Alex, „logiczne matematyki”? Dlatego matematycy są słabymi programistami. Nie zrozum mnie źle; dobrzy programiści potrafią również rozumieć matematykę. Ale to nie ma nic wspólnego z logiką matematyczną. Jest to konstrukcja językowa, która przy dowolnym wyrażeniu, przynajmniej w Javascripcie, !przekształci go w boolean. Dodanie kolejnego !spowoduje zanegowanie tego boolean. Rzutowanie jest tutaj niejawne, a efekt końcowy działa. Nie ma potrzeby -1.
Yanick Rochon

1
wcale nie jestem matematykiem. możesz spróbować i zobaczyć siebie jsperf.com/javascript-boolean-test
Alex K

4

Jeśli możliwe wartości v to tylko 0 i 1, to dla dowolnej liczby całkowitej x wyrażenie: v = Math.pow ((Math.pow (x, v) - x), v); zmieni wartość.

Wiem, że to brzydkie rozwiązanie i OP nie szukał tego ... ale myślałem o innym rozwiązaniu, kiedy byłem w toalecie: P




1

Jeśli są tylko dwie wartości, tak jak w tym przypadku (0, 1), uważam, że marnowanie int jest niepotrzebne. Raczej idź na boolean i pracuj w bitach. Wiem, że zakładam, ale w przypadku przełączania między dwoma stanami wartość logiczna wydaje się idealnym wyborem.


1

Cóż, jak wiemy, że w javascript tylko porównanie boolowskie da również oczekiwany wynik.

to znaczy v = v == 0 wystarczy do tego.

Poniżej znajduje się kod do tego:

var v = 0;
alert("if v  is 0 output: " + (v == 0));

setTimeout(function() {
  v = 1;
  alert("if v  is 1 Output: " + (v == 0));
}, 1000);

JSFiddle: https://jsfiddle.net/vikash2402/83zf2zz0/

Mam nadzieję, że to ci pomoże :)


Działa to do przełączania wartości, ale wartość nie przełącza się między 0 a 1, ale raczej między truei false. Możesz użyć v == 0do ustalenia wartości zmiennej w warunku, ale jeśli chcesz użyć wartości 0 lub 1, musisz użyć czegoś podobnego v == 0 ? 0 : 1lub Number(v)uzyskać. (Możesz także użyć v = !v;do przełączania między truei false.)
Guffa,

tak, rozumiem .. dziękuję :)
Vikash Pandey

0

v = liczba (! v)

Wpisz typ rzutowania Odwróconą wartość logiczną na Liczba, która jest pożądanym wynikiem.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.