V = (v == 0? 1: 0) yazmanın daha iyi bir yolu var mı? [kapalı]


465

Bir değişkeni 0 ile 1 arasında değiştirmek istiyorum. 0 ise 1 olarak ayarlamak istiyorum, 1 ise 0 olarak ayarlamak istiyorum.

Bu öyle temel bir işlem ki sık sık yazıyorum ki mümkün olan en kısa ve en net yolu araştırmak istiyorum. İşte şimdiye kadarki en iyim:

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

Bunu geliştirebilir misin?

Düzenleme: soru netliği korurken yukarıdaki ifadeyi en az karaktere nasıl yazacağınızı soruyor - bu 'gerçek bir soru' nasıl değil? Bu, bir kod-golf egzersizi olarak tasarlanmamıştı, ancak bazı ilginç cevaplar golf olarak yaklaşan insanlardan çıktı - golfün yapıcı ve düşündürücü bir şekilde kullanıldığını görmek güzel.


20
Bu zaten basit / net / kısa görünüyor.
Mafya

136
hile:v = +!v;
jAndy

48
'Daha iyi' aynı zamanda 'daha hızlı' anlamına da gelirse : jsperf.com/v-0-1-0 .
pimvdb

7
@Mobinga: +1. Bu olması gerektiği kadar basit. Gördüğüm diğer tüm cevaplar kafa karıştırıcı ve bazıları mantığı değiştiriyor; böcek tanıtımı.
Ian Boyd

8
@holodoc Fikrinizi ifade etmek için daha iyi bir çözüm, orijinalin en iyi yol olduğunu düşündüğünüzü ve neden böyle olduğunu düşündüğünüzü açıklayan bir cevap oluşturmak olacaktır. bu da diğer kişilerin cevabınızı oylayarak kolayca yanıtlamalarını sağlar.
Chuck van der Linden

Yanıtlar:


721

Sadece şunu kullanabilirsiniz:

v = 1 - v;

Bu elbette değişkenin doğru şekilde başlatıldığını, yani sadece 0 veya 1 değerine sahip olduğunu varsayar.

Daha kısa ancak daha az kullanılan bir operatör kullanan başka bir yöntem:

v ^= 1;

Düzenle:

Açık olmak gerekirse; Bu soruna asla kod golfü olarak yaklaşmadım, sadece operatörlerin yan etkileri gibi belirsiz hileler kullanmadan görevi yapmanın kısa bir yolunu bulmak için.


206
Bunlar, ince kesilmiş cam veya nadir çiçekli orkide gibi güzel kod satırlarıdır. Doğrudan mantıksal katmandan nasıl ulaştığınızı ve mümkün olan en uygun işlemlerle 1 ve 0 matematiğini nasıl ele aldığınızı seviyorum. Bunları kendi projelerimde kullanacağım, ancak maalesef kodun iş arkadaşları tarafından anlaşılması gerektiğinde varsayılan olarak daha mantık tabanlı bir yaklaşıma ihtiyacım olacak. Yine de teşekkür ederim, cevabım benim günümü yaptı.
Ollie Glass

37
Her zaman kodun ne yaptığını belirten bir yorum ekleyebilirsiniz.
Prusse

25
@Kevin: Bunun soruyu sorulduğu gibi açıkça cevaplamadığı doğru değil. Q, "0 ile 1 arasında bir değişkeni değiştirmek istiyorum." Dedi. Çok makul bir yorum, bunun değişkenin değerinin zaten 0 veya 1 olduğunu ima etmesidir. Bu yorum / sınırlama cevapta açıkça belirtilmiştir. Dünyada neye itiraz edebilirsiniz?
LarsH

50
@Matthew, v ^= 1net bulamayan birinin programlamayı durdurması gerektiğini söylemek biraz zor. Daha önce de belirtildiği gibi, daha yaygın operatörlerden biri değildir ve aynı şeyi yapmaz v = v ^ 1. Ayrıca operatör farklı dillerde (VB) tamamen farklı bir şey ifade eder. Evet, hızlı bir arama size bir XOR operatörü olduğunu ve ne yaptığını anlayacağınızı söyleyecektir, ancak birçoğu için ilk bakışta açık olmayabilir. Bunun işini bırakman gerektiği anlamına gelmediğini sanmıyorum.
JD Isaacks

80
Bunu yazarak 15 karakter kaydederseniz, ancak açıklamak için 40 karakterlik yorum kullanırsanız, bu gerçekten bir gelişme mi?
Michael Myers

343

Çünkü 0bir falsedeğerdir ve 1bir truedeğerdir.

v = (v ? 0 : 1);

Kullanmaktan memnunsanız trueve falsesayılar yerine

v = !v;

veya sayı olması gerekiyorsa:

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

55
sadece büyüyü +ondan önce koy !. Ohhh çok kirli görünüyor! ama havalı: p
jAndy

1
@Quentin - eğer varsa switch(v){ case 0 ...ya da (v == 0) ya da v === 0 ise adamın kodunu kıracaktır .... Yaklaşmasına ek olarak sonucunu değiştiriyorsunuz ....
Brian

34
Bunun bir surat yapın: ({v :+! v}).v.
pimvdb

17
@Brian: o sihirli +işaretle değil! ¯ \ _ (ツ) _ / ¯
jAndy

11
v = (v ? 0 : 1)Net ve deyimsel JS için +1 .
Bennett McElwee

200

v = (v + 1) % 2Daha değerlere arasında geçiş yapmak gerekirse sadece değiştirmek 2için (n + 1). Diyelim ki sadece 0,1,2 döngü yapmalısınız v = (v + 1) % 3.


2
Döngüyü seviyorum! Bu gerçekten akıllı.
Ollie Glass

16
Bir döngü olarak geçişi düşündüğünüz için +1. Ne kadar esnek olduğunu dikkate alarak basit.
Guffa

3
Ayrıca sağlam olan modüler bir çözüm sağlamak için +1. Pratikte muhtemelen const2, 3, ... sihirli sayıları yerine bir değişken kullanmak istersiniz
oosterwal

2
Daha kısa (hackier) yol: ++v % 30, 1, 2 arasında geçiş yapmak istiyorsanız
haraldmartin

75

Bunun için bir işlev yazabilir ve aşağıdaki gibi kullanabilirsiniz:

v = inv(v)


30
+1 Bunun en temiz çözüm olduğuna kesinlikle katılıyorum (... ama sonra invişleve giren şey : P)
Lea Hayes

4
Keşke bu cevabı +1'den daha fazla verebilseydim. Ortak kod körü körüne belli değilse, açıklayıcı bir isme sahip bir fonksiyona sarılmalıdır.
TehShrike

11
@TehShrike invaçıklayıcı bir isim mi düşünüyorsunuz?
Bennett McElwee

3
@Bennett McElwee: inv = ters çevirin. Her zaman benim için ortak bir kısaltma gibi görünüyordu.
Daniel

51
O zaman neden kısaltın, 'ters çevir' veya 'değiştir' olarak adlandırın ve kodun okunabilir olmasını sağlayın. bu şeyleri 80 sütunlu bir punchcard'a veya başka bir şeye sığdırmaya çalışıyormuşuz gibi değil.
Chuck van der Linden

50

1 dışında bir olasılıkla ilgilenmiyorsanız:

v = v ? 0 : 1;

Yukarıdaki durumda, v 0, false, undefined veya null ise v 1 olur. Bu tür bir yaklaşımı kullanarak dikkatli olun - v "merhaba dünya" olsa bile v 0 olacaktır.


2
Bu değeri çevirmeyecek. Yani v = v ? 0 : 1.
Guffa

3
@Guffa - Disleksi yakalamak için +1 ...
Brian

3
Bu, arkadaşlarımla kullanabileceğim en sevdiğim mantık tabanlı cevabım (@ Guffa'nın cevabını sayı tabanlı olarak görüyorum). Gereksiz testi (v == 0) ve parantezleri nasıl çıkardığınızdan hoşlanıyorum, mutlak minimum karakter sayısına kadar sıyırıyorum. Teşekkür ederim.
Ollie Glass

1
Ben de @ Guffa'nın cevabının büyük bir hayranıyım - lynard skynard'ın sözleriyle, basit tutun adam;)
Brian

2
+1 "doğruluk" değerlerini anlamak için.
zzzzBov

44

İşi halledecek v = 1 - vya v ^= 1da v= +!valacak hatlar var , ancak bunlar kesmek olarak adlandırdığım şeyi oluşturur. Bunlar güzel kod satırları değil, amaçlanan etkiye sahip ucuz numaralardır. 1 - v"değeri 0 ile 1 arasında değiştir" iletişim kurmaz. Bu, kodunuzu daha az etkileyici hale getirir ve başka bir geliştiricinin kodunuzu ayrıştırması gereken bir yer (küçük de olsa) sunar.

Bunun yerine benzer bir işleve sahip olmak v = toggle(v), amacı en hızlı şekilde iletir.


8
-1, ciddiye, v=1-vgeçiş iletişim değil?
Blindy

22
1-vgerçekten geçiş yapabilir, ancak iletişim kurduğu tek şey budur. Örneğin, sıfır noktasında bir çizgi v=1veya ortalanmış bir yansıtma dönüşümü de iletebilir v=0.5. Bu anlamda nispeten belirsizdir. Bunun vyalnızca amaçlanan anlamı olabileceğini 0veya 1sınırlayabileceğini bilmenin , ancak diğer geliştiricileri (veya gelecekteki benliğinizi) bu basit çizgiyi anlayabilmeden önce bu bağlamı anlamaya zorladığı doğrudur . Bundan daha net olamazsınızv = toggle(v)
Ray

10
v ^= 1mantıklı işlemleri anlarsanız mükemmel bir şekilde anlaşılır ve programcıysanız daha iyi olursunuz. Bence bu ve v=1-v; biri mantıksal bir işlemdir ve aritmetik bir işlemdir ve matematiksel değil mantıksal bir kavramı temsil etmeye çalışıyoruz.
Matthew

6
@Matthew Oku: Bu düşüncelerimi özetleyen harika bir ifadedir: "matematiksel değil mantıksal bir kavramı temsil etmeye çalışıyoruz." Yine v ^= 1de, bir bit-xor olarak yorumlanabileceği için, bir belirsizliğe sahiptir.
Ray

6
programcılar için (ve evet, bizim gibi meraklıları kastediyorum), bunlar oldukça açık. Onlar hack değil, çünkü sadeliklerinden dolayı zarif çözümler.
gion_13

38

( Dürüstlük ve matematiksel bütünlük - bu "cevap" üzerindeki oy sayısı göz önüne alındığında - bu cevabı düzenlememe yol açtı. Mümkün olduğunca uzun süre bekledim çünkü "derin" bir şey olarak değil, "derin" bir şey olarak düşünülmüştü. herhangi bir açıklama amaca ters gibi görünüyordu. Ancak, yorumlar yanlış anlama önlemek için net olması gerektiğini açıkça gösteriyor. )

Orijinal cevabım:

Spesifikasyonun bu bölümünün ifadeleri:

0 ise, 1 olarak ayarlamak istiyorum, aksi takdirde 0 olarak ayarlamak istiyorum.

en doğru çözümün:

v = dirac_delta(0,v)

Birincisi, itiraf: Ben yaptım benim delta fonksiyonları karıştı olsun. Kronecker deltası biraz daha uygun olurdu, ancak alandan bağımsız bir şey istediğim kadar değil (Kronecker deltası esas olarak sadece tamsayılar için kullanılır). Ama delta fonksiyonlarını hiç kullanmamalıydım, söylemeliydim:

v = characteristic_function({0},v)

Açıklığa kavuşturayım. Bir fonksiyonun üçlü olduğunu (X, Y, f) hatırlayın , burada X ve Y kümelerdir ( sırasıyla domain ve codomain olarak adlandırılır) ve f , X'in her elemanına Y elemanını atayan bir kuraldır . Genellikle üçlüyü (X, Y, f) f: X → Y olarak yazarız . X'in bir alt kümesi , örneğin A , verilen bir işlev χ olan bir karakteristik fonksiyon vardır (ℕ veya ℝ gibi daha büyük bir alan adına bir fonksiyon olarak da düşünülebilir). Bu işlev kural tarafından tanımlanır: bir X → {0,1}:

χ A (x) = 1 , x ∈ A ve χ A (x) = 0 , x ∉ A ise .

Eğer gerçeği tablolar gibi, bu soru için doğruluk tablosu ise "öğesi mi x ait X alt kümesi unsuru A ?".

Yani bu tanımdan, karakteristik fonksiyonun burada gerekli olduğu açıktır, X ile 0 ve A = {0} içeren bazı büyük setler vardır . Ben ne olmalıdır yazdım.

Ve böylece delta fonksiyonlarına. Bunun için entegrasyon hakkında bilgi sahibi olmalıyız. Ya zaten biliyorsun ya da bilmiyorsun. Eğer yapmazsanız, burada söyleyebileceğim hiçbir şey size teorinin inceliklerini anlatamaz, ama bir cümle özeti verebilirim. Bir X kümesi üzerinde esasen "ortalamaların çalışması için gerekli olan" ölçüsü vardır . Yani, biz bir dizi varsa yani X'i ve bir ölçü ^ ı o sette ardından fonksiyonları bir sınıf yoktur X → ℝ denilen, ölçülebilir fonksiyonlar ifadesi hangi x f dμ bazı belirsiz anlamda mantıklı ve olduğunu f'nin X üzerinden "ortalaması" .

Bir kümedeki ölçü verildiğinde, o kümenin alt kümeleri için bir "ölçü" tanımlanabilir. Bu, bir alt kümeye karakteristik fonksiyonunun integralini atayarak yapılır (bunun ölçülebilir bir fonksiyon olduğu varsayılarak). Bu olabilir sonsuz veya tanımlanmamış (iki ustaca farklıdır).

Etrafta birçok önlem var, ama burada önemli olan iki tane var. Birincisi, gerçek çizgideki standart ölçüdür ℝ. Bu önlem için, f dμ okulda öğrettiğiniz şeydir (matematik hala okullarda öğretiliyor mu?): Küçük dikdörtgenleri toplayın ve daha küçük ve daha küçük genişlikler alın. Bu ölçümde, bir aralığın ölçüsü genişliğidir. Bir noktanın ölçüsü 0'dır.

Herhangi bir sette çalışan bir diğer önemli ölçüye nokta ölçüsü denir . Bir fonksiyonun integrali , değerlerinin toplamı olacak şekilde tanımlanır:

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

Bu hesaplama, her bir tektona hesaplama 1'i atar. Bu, bir alt kümenin yalnızca ve eğer sonlu olması durumunda sonlu ölçüme sahip olduğu anlamına gelir . Ve çok az fonksiyonun sonlu integrali vardır. Bir fonksiyonun sonlu bir integrali varsa, sadece sayılabilen sayıda noktada sıfırdan farklı olmalıdır . Yani muhtemelen bildiğiniz fonksiyonların büyük çoğunluğu bu önlem altında sonlu integral içermez.

Ve şimdi delta fonksiyonlarına. Çok geniş bir tanım alalım. Ölçülebilir bir alanımız (X, μ) (bu, üzerinde bir ölçü olan bir küme) ve bir ∈ X elemanı var . Bu "tanımlar" delta fonksiyonu (bağlı bir "işlev" olmak üzere) δ bir X → ℝ: bu özelliği ile δ bir (x) = 0 ise X ≠ bir ve x δ bir dμ = 1 .

Bu konuda bilgi sahibi olmak için en önemli gerçek şudur: Delta işlevinin bir işlev olması gerekmez . O edilir değil düzgün tanımlanmış: Ne söylemedim ö bir (a) olduğunu.

Bu noktada ne yaptığınız, kim olduğunuza bağlıdır. Buradaki dünya iki kategoriye ayrılıyor. Bir matematikçiyseniz, aşağıdakileri söylersiniz:

Tamam, delta işlevi tanımlanmayabilir. Nerede biz bunun için uygun bir ev bulabilirse edelim onun varsayımsal özelliklerine bakmak ve görmek olduğunu belirledi. Bunu yapabiliriz ve dağıtımlarla sonuçlanırız . Bunlar değil (ille) işlevlerini, ama işler olduğunu bir fonksiyonlar gibi küçük ve onlar fonksiyonlar sanki sık sık onlarla çalışabilir davranırlar; ancak sahip olmadıkları bazı şeyler vardır ("değerler" gibi), bu yüzden dikkatli olmalıyız.

Bir matematikçi değilseniz, şunları söylersiniz:

Tamam, bu nedenle delta işlevi düzgün tanımlanmamış olabilir. Kim böyle söylüyor? Bir grup matematikçi mi? Boşver onları! Ne biliyorlar?

Şimdi izleyicilerimi rahatsız ettikten sonra devam edeceğim.

Dirac delta genellikle standart bir ölçüsü olan gerçek hattının üzerinde bir noktada (genellikle 0) delta fonksiyonu olarak alınır. Yani benim deltalarımı bilmeyen yorumlarımda şikayet edenler bunu yapıyor çünkü bu tanımı kullanıyorlar. Onlara özür dilerim: Mathematician'ın savunmasını kullanarak ( Humpty Dumpty tarafından popülerleştirildiği gibi : basitçe her şeyi yeniden tanımlayın) doğru bir şekilde tanımlamakla birlikte, farklı bir şey ifade etmek için standart bir terim kullanmak kötü bir formdur.

Ama olan bunu yapmak istiyorum ve onu Burada ihtiyacım olanı olanı yapmak yapan bir delta fonksiyonu. Bir alırsak nokta ölçü kümesi üzerinde X sonra orada olan hakiki fonksiyonu δ bir X → ℝ: hangi karşılar bir delta fonksiyonu kriterlerini. Biz bir işlev arıyor Bunun nedeni X → ℝ haricinde sıfır olan bir ve böyle onun tüm değerlerini toplamı 1. Böyle bir fonksiyonu basit olduğunu: bilginin yalnızca eksik parçası onun değeridir bir ve toplamı 1 olarak almak için sadece 1 değerini atarız. Bu, {a} üzerindeki karakteristik fonksiyondan başka bir şey değildir . Sonra:

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

Bu durumda, tek bir set için karakteristik fonksiyon ve delta fonksiyonu aynı fikirdedir.

Sonuç olarak, burada üç "işlev" ailesi vardır:

  1. Tekli setlerin karakteristik fonksiyonları,
  2. Delta fonksiyonları,
  3. Kronecker deltası çalışır.

Bunlardan ikincisi en genel olanıdır, çünkü diğerlerinden herhangi biri nokta ölçüsünü kullanırken buna bir örnektir. Ancak birinci ve üçüncü, her zaman gerçek işlevler olma avantajına sahiptir. Üçüncüsü, belirli bir alan ailesi (tamsayılar veya bazı alt kümeleri) için ilkinin özel bir durumudur.

Başlangıçta cevabı yazarken Yani, son olarak değil düzgün düşünme (ben olduğunu söylemek kadar ileri gitmezdim karıştı ben gösterdiğimiz umut olarak, do ne zaman bahsettiğimi biliyorum Aslında önce düşünüyorum, çok fazla düşünmedim). Dirac delta olağan anlamı burada istedi ama benim cevap noktalarından biri giriş alanı olmasıydı ne değildir değil Kronecker delta da doğru olmazdı böylece tanımlanmış. Bu yüzden (amaçladığım) en iyi matematiksel cevap karakteristik fonksiyon olurdu .

Umarım bunların hepsi açıktır; ve umarım TeX makroları yerine HTML objeleri kullanarak bir daha asla matematiksel bir parça yazmam gerekmiyor!


37
+1 - Quentin'i dirac_delta işlevini bilmediği için indirebilirsem yapardım. Hangi üniversiteye gittiğini bilmek istiyorum, çünkü dijital işlemenin temelini bile bilmiyorlarsa oradan kimseyi işe alacağımı sanmıyorum. Quentin'i, denediğiniz mizahı anlayamadığı için aşağı inerdim.
Dunk

23
Eğer anlamadığım her cevabı düşürürsem ... Bir çok cevabı küçümserdim.
Seamus

4
Merhaba Andrew, uzun zaman oldu.
Tim Down

4
@Tim: İyi keder, bu yüzden var! Peki Bermuda Piskoposu nasıl? (Bunu hatırladım mı?) Bu yorum dizisini yakalamak için en iyi yer değil sanırım ... 17 yıl değil mi?
Andrew Stacey

3
@ Cԃ ա ԃ "Bu cevap ... başarısız oldu" sigh . Matematikçi olduğumu okudun, değil mi? Bu cevap bir vakumda küresel bir programcı için mükemmel çalışıyor, bu yüzden ne hakkında şikayet ettiğinizi bilmiyorum.
Andrew Stacey

35

Yapabilirsin

v = Math.abs(--v);

Bu azalma değeri 0 veya -1 olarak ayarlar ve -1'i +1'ye Math.absdönüştürür.


27
Bu, 'Basit bir görev için 10000 yol oluştur' yarışmasına dönüştü. Ve tüm yolları seviyorum haha.
Josh

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

15
@Benoit - formülünüz v = 0 ve v = 1 için 1'e eşittir. Bu doğru olsa! v = Math.round(Math.cos(Math.PI/((v*2+1)+2)-2*v));: D
Teo.sk

2
Bu asla değeri değiştirmez. Eğer v = 1öyleyse v = Math.Abs(-1)+1. Eğer v = 0öyleyse v = Math.Abs(-0)0.
Paul

1
+1 Ve bu benim diğeriydi ... Grr.
özyinelemeli

34

genel olarak, iki değer arasında geçiş yapmanız gerektiğinde, geçerli değeri iki geçiş değerinin toplamından çıkarabilirsiniz:

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

2
Bu ilginç ve yaratıcı ama potansiyel olarak tehlikelidir. Eğer vbozuk olur aniden iki farklı değer arasında geçiş başlayacaktır. (Dikkate alınması gereken bir şey ...)
oosterwal

1
İlginç fikir için +1. OP'nin ya da başkasının aslında bu koşullarda kullanacağı değil, bu bilgi parçası beyinde sonsuza dek var olmalıdır.
Shimmy Weitzhandler

3
@oosterwal: O zaman kesinlikle sorun yolsuzluk ile ilgili ...
GManNickG

@GManNickG: Er ya da geç veri bozulması olacak, bu yüzden tespit etmemenin sonucunun farkında olmalıyız. Eğer vnormalde dönüşümlü, üç veya daha fazla devlet listesinden iki devletin yürütmek için kullanılan daha sonra bir yolsuzluk vbu beklenmeyen ve istenmeyen sonuçlara yol açabilir - dönüşümlü tamamen farklı iki durumlarını yürütmek için programın neden olabilir. Bundan çıkarılacak ders şudur: Verilerinizde daima güvenilirlik kontrolleri yapın.
oosterwal

33

1 veya 0 tamsayısı olması gerekiyorsa, parantez gerekli olmasa da, yaptığınız işlem iyi olur. Bunlar a boolean olarak kullanılacaksa, şunları yapabilirsiniz:

v = !v;

10
Bu, Ollie'nin "v" değerinin bir tamsayı yerine boole sonucuna ayarlanmasına neden olmaz mı?
Brian

12
Evet olacak ve kod satırının üzerindeki cümlede uyardım. Bunlar a
boolean

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

Yeterlidir !


7
Bir cevaptan daha çok bir fikir, değil mi?
Brian

16
@Brian: 'daha iyi' aslında sadece fikir ile ilgilidir.
pimvdb

3
Köşeli parantezleri nasıl çıkardığınızdan hoşlanıyorum - bu birkaç karakteri düzeltir!
Ollie Glass

9
@Brian: " Cevap " "Hayır, daha iyi bir yazma yolu yok v = (v==0 ? 1 : 0);" . Herkes golf oynamak için farklı yollar buluyor; ve aslında soruyu cevaplamıyor. Bu yüzden bu cevaba oy verdim.
Ian Boyd

19

Çözümlerin listesi

Önermek istediğim üç çözüm var. Hepsi için herhangi bir değer dönüştürmek 0(eğer 1, truevb) ya da 1(eğer 0, false, nullvs.):

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

ve ek olarak, daha önce bahsedilen, ancak akıllı ve hızlı (yalnızca 0s ve 1s için çalışıyor olsa da ):

  • v = 1-v

Çözüm 1

Aşağıdaki çözümü kullanabilirsiniz:

v = 1*!v

Bu ilk (ters boolean tamsayı dönüştürür 0için Trueve başka bir değer False) ile çarparak zaman sonra tamsayı olarak tedavi edecek 1. Sonuç 0olarak dönüştürülür 1ve diğer herhangi bir değer 0.

Bir kanıt olarak bu jsfiddle bakın ve test etmek istediğiniz değerleri sağlayın: jsfiddle.net/rH3g5/

Sonuçlar aşağıdaki gibidir:

  • -123tamsayıya dönüştürülecek 0,
  • -10tamsayıya dönüştürülecek 0,
  • -1tamsayıya dönüştürülecek 0,
  • 0tamsayıya dönüştürülecek 1,
  • 1tamsayıya dönüştürülecek 0,
  • 2tamsayıya dönüştürülecek 0,
  • 60tamsayıya dönüştürülecek 0,

Çözüm 2

Mblase75'in belirttiği gibi, jAndy'nin benimki gibi çalışan başka bir çözümü vardı:

v = +!v

Ayrıca ilk olarak boolean'ı orijinal değerden yapar, ancak tamsayıya dönüştürmek +yerine kullanır 1*. Sonuç tamamen aynıdır, ancak gösterim daha kısadır.

Çözüm 3

Başka bir yaklaşım ~~operatörü kullanmaktır :

v = ~~!v

Oldukça nadirdir ve her zaman boole'den tamsayıya dönüşür.


JavaScript'te, bir değişkeni +bir sayıya dönüştürmek için önek kullanabilirsiniz , böylece +!vçözümünüze eşdeğerdir (OP'nin yorumlarındaki jAndy'nin çözümü).
Blazemonger

@ mblase75: Evet, boolean'ı tamsayıya dönüştürmeye çalışırken 1*değiştirilebilecek haklısınız +. Cevabımdaki diğer her şey aynı kaldı. jAndy'nin cevabı doğru, ama benimki daha ayrıntılı. Cevabımı çözümüne ekleyeceğim.
Tadeck

@ Güzel bir fikir için +1'yi kontrol edin.
Shimmy Weitzhandler

17

Başka bir cevabı, bir yorumu ve kendi fikrimi özetlemek için, iki şeyi birleştirmenizi öneririm:

  1. Geçiş için bir işlev kullanma
  2. Bu işlevin içinde daha okunabilir bir uygulama kullanın

İşte bir kütüphaneye yerleştirebileceğiniz veya başka bir Javascript Framework için bir Eklentiye sartabileceğiniz işlev.

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

Ve kullanımı basitçe:

v = inv(v);

Avantajları:

  1. Kod Çoğaltma Yok
  2. Siz veya herhangi biri gelecekte bunu tekrar okuduysa, kodunuzu en kısa sürede anlayacaksınız.

Öyle mi? Hızlı bir test yaptım : jsperf.com/function-vs-no-function/2 ve öyle görünüyor ki, fark o kadar da değil.
Martin Schlagnitweit

25
7.5ns ve 8.8ns. Bu ekstra 1.3 nanosaniye sizi gerçekten öldürecek.
Ian Boyd

5
Kurtardığım her zaman ailemi Disney World'e götürdüm! :-)
Tom

1
Tamamen doğru. "Akıllı" çözümler yazan insanlar muhtemelen diğer programcılar "taşlar" kodunu korumak zorunda değildi
Avi

1
neden olmasın function toggle(i){ return i == 0 ? 1 : 0 }?
Billy Moon

13

Neden kendi boolean'larını inşa etmek istediğini bilmiyorum? Funky sözdizimlerini seviyorum, ama neden anlaşılabilir kod yazmıyorsunuz?

Bu en kısa / hızlı değil, ancak en net (ve herkes için okunabilir) iyi bilinen if / else durumunu kullanmaktır:

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

Gerçekten net olmak istiyorsanız, bunun için sayılar yerine boolean kullanmalısınız. Çoğu vaka için yeterince hızlıdırlar. Booleans ile kısaca kazanacak bu sözdizimini kullanabilirsiniz:

v = !v;

1
Aslında benim tercih ettiğim cevap bu olurdu; ama üçlü operatör vs if-else sigortayı aydınlatmak istemediğim kutsal bir savaştır. Bununla birlikte, ilk satırın olması gerektiğini düşünüyorum === 0. Örnek girişi ile 7doğru çıkış olur 0, ancak bu çıkacaktır 1.
Ian Boyd

4
Bir tür istisna atmak yerine 7 gibi bir girdiyi sessizce düzeltmenin bir değeri var mı? Başka bir kod biraz daha sadece 0 veya 1 beklerken 7, eller kodunuzu değeri düzeltmeden önce el aldı varsa ne demek?
Chuck van der Linden

12

Orijinal çözümünüzün başka bir formu:

v = Number(v == 0);

EDIT: Orijinal çözümümdeki hatayı işaret ettikleri için TehShrike ve Guffa'ya teşekkürler.


4
== işleci, birçok sistem altında bir boole (tamsayı yerine) döndürür. Bu, yalnızca v bir tamsayı olarak tanımlandıysa ve dil, boole'den tamsayıya otomatik döküm ile soğuksa işe yarardı.
TehShrike

Çok doğru. Soruyu javascript bağlamında cevaplıyordum (soru nasıl etiketlendi).
Kurt Kaylor

@Kurt Kaylor: Javascript, == operatörünün bir boole döndürdüğü sistemlerden biridir, bu nedenle orijinal çözümle aynı şeyi yapmaz.
Guffa

@Guffa: Javascript'in örtük tür dönüşümü olan zayıf yazılan bir dil olması gerçeğinden faydalanıyorum (örn. '0.0000 '== 0, 0 == "", false == "", false == 0, 1 == doğru, vb.). Döndürülen boole değerini 0 veya 1 tamsayısını kullanabildiğim gibi kullanabilirim. Örneğin, bir javascript konsolunda "2 + true" değerini değerlendirmeye çalışın, 3 elde edersiniz.
Kurt Kaylor

1
@Kurt Kaylor: Bu sadece örtük bir dönüşümü zorladığınız durumlarda işe yarar. Örneğin deneyin 'opacity:'+trueve opacity:trueyerine bununla bitirin opacity:1.
Guffa

11

Daha açık yapardım.

Ne anlama vgeliyor?

Örneğin, v bir durum olduğunda. Nesne Durumu oluşturun. DDD'de bir değer nesnesi.

Mantığı bu değer nesnesine uygulayın. Daha sonra kodunuzu daha işlevsel bir şekilde daha okunaklı bir şekilde yazabilirsiniz. Geçiş durumu, mevcut duruma göre yeni bir Durum oluşturularak yapılabilir. İf ifadeniz / mantığınız daha sonra nesnenize dahil edilir ve birim test edebilirsiniz. Bir valueObject her zaman değişmezdir, bu nedenle kimliği yoktur. Bu yüzden değerini değiştirmek için yeni bir değer oluşturmanız gerekir.

Misal:

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
aşırı mühendislik?
alejandro5042

6
Beni güldürmek için +1
Denshi


10

Bu eksik:

v = [1, 0][v];

Yuvarlak robin olarak da çalışır:

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 ...

Veya

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

Son çözümün charme, diğer tüm değerlerle de çalışır.

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

Çok özel bir durum için, (değişen) bir değer almak ister ve undefinedbu model yardımcı olabilir:

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

9

Bu JavaScript olduğundan, +int'e dönüştürmek için tekli olanı kullanabiliriz :

v = +!v;

Bu NOTdeğer mantıklı olacaktır v( trueif v == 0veya falseif vererek v == 1). Ardından, döndürülen boole değerini karşılık gelen tamsayı gösterimine dönüştürürüz.


8

Sadece vuruşlar için: v = Math.pow(v-1,v)1 ile 0 arasında geçiş yapar.


7

Bir tane daha: v=++v%2

(C'de basit olurdu ++v%=2)

ps. Evet, çift atama olduğunu biliyorum, ama bu sadece C yönteminin ham yeniden yazımı (olduğu gibi çalışmıyor, JS ön artış operatörünün değer değeri döndürmemesine neden oluyor.


3
C sürümünüz yasal değil; bir ++operatörün sonucunu değiştiremezsiniz (bu bir değer değildir). Gelince v=++v%2, viki kez değiştiriyorsunuz . Bunun JavaScript'te iyi tanımlanmış olup olmadığını bilmiyorum, ancak gerekli değil. v = (v+1) % 2.
Keith Thompson

En azından içinde c++- artım öncesi operatör daha yüksek önceliğe sahiptir ve 'yerinde' değişkeni değiştirir, bu nedenle değer olarak kullanılabilir. Ben JS uygulanması ++bir lvalue olarak tedavi edilemez olduğunu düşünüyorum: / Ve evet, bu gereksiz, ama ben sadece başka bir yöntem göstermeye çalışıyordum - zaten daha iyi çözümler gönderildi :)
Adam Jurczyk

3
+1. V = (v + 1)% 2 olarak yazılabilir.
niktrs

7

Girişinizin 1 veya 0 olduğu garanti edilirse, şunları kullanabilirsiniz:

v = 2+~v;

7

{1,0} dizisini tanımlayın, v'yi v [v] olarak ayarlayın, bu nedenle 0 değeri olan v 1 olur ve tersi de geçerlidir.


Benim çözümüm doğru, hoşuna gitmiyorsa nedenini yaz. Yorumunuz kimseye yardım etmiyor. Çözümüm, karar vermekten farklı olarak bir değişkeni okuyor. Bu daha az CPU gerektirir.
S ..

5

Bunu yapmanın başka bir yaratıcı yolu, vherhangi bir değere eşit olmakla, her zaman geri döner 0veya1

v = !!v^1;

3
iki !!mantıksal matematik hiçbir şey sonuç, !!!!oraya koymak ve aynı olacak ama sonuç 4 4 gereksiz operasyonlar
Alex K

10
@Alex: bir boole dökülecek !!. !!(1) === trueve!!(0) === false
nickf

1
@nickf: aha, bu yüzden v = Boolean(v^1)daha bilgilendirici olurdu, açıkladığınız için teşekkürler - döküm hakkında düşünmedim
Alex K

1
@Alex, "mantıksal matematik"? Bu yüzden matematikçiler zayıf programcılardır. Beni yanlış anlamayın; iyi programcılar da matematiği anlamada iyidir. Fakat bunun mantıksal matematikle bir ilgisi yok. Herhangi bir ifade verildiğinde, en azından Javascript'te, !onu boole çevirecek bir dil yapısıdır . Başka bir tane eklemek !bu booleanı reddeder. Döküm burada örtülüdür ve sonuç çalışır. -1'e gerek yoktur.
Yanick Rochon

1
ben hiç matematikçi değilim. bunu deneyebilir ve kendinizi görebilirsiniz jsperf.com/javascript-boolean-test
Alex K

4

V için olası değerler sadece 0 ve 1 ise, herhangi bir x tamsayısı için: v = Math.pow ((Math.pow (x, v) - x), v); değeri değiştirir.

Bunun çirkin bir çözüm olduğunu biliyorum ve OP bunu aramıyordu ... ama tuvalette olduğumda başka bir çözüm düşünüyordum: P




1

Bu durumda (0, 1) olduğu gibi sadece iki değer varsa, int kullanmanın israf olduğuna inanıyorum. Daha ziyade boolean'a gidin ve bitlerle çalışın. Sanırım varsayıyorum ama iki eyalet arasında geçiş olması durumunda boolean ideal bir seçim gibi görünüyor.


1

Javascript'te sadece Boole karşılaştırmasının size beklenen sonucu vereceğini bildiğimiz gibi.

yani v = v == 0bunun için yeterlidir.

Bunun kodu aşağıdadır:

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/

Bunun size yardımcı olacağını umuyoruz :)


Bu, bir değeri değiştirmek için çalışır, ancak değer 0 ile 1 arasında değil, trueve arasında değişir false. Bir koşuldaki v == 0değişkenin değerini belirlemek için kullanabilirsiniz , ancak 0 veya 1 değerini kullanmak istiyorsanız, böyle bir şey kullanmanız v == 0 ? 0 : 1veya Number(v)bunu elde etmeniz gerekir . (Ayrıca, ve v = !v;arasında geçiş yapmak için de kullanabilirsiniz .)truefalse
Guffa

evet anladım .. teşekkür ederim :)
Vikash Pandey

0

v = Sayı (! v)

Ters Boolean değerini İstenen çıktı olan Sayıya döküm olarak yazacaktır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.