有没有更好的写作方式v =(v == 0?1:0);

我想切换0和1之间的variables。如果它是0,我想将其设置为1,否则,如果它是1我想将其设置为0。

这是一个非常基本的操作,我经常写这个操作,我想调查一下最短,最清晰的方法。 这是我迄今为止最好的:

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

你能改进吗?

编辑:问题是如何在保持清晰度的同时用最less的字符来编写上述语句 – 这是不是一个真正的问题? 这不是打算做高尔夫练习,尽pipe一些有趣的答案已经从高尔夫球接近人们那里得到了 – 很高兴看到高尔夫以一种build设性和发人深省的方式被使用。

你可以简单地使用:

 v = 1 - v; 

这当然假定variables被正确初始化,即它只有值0或1。

另一种较短的方法,但使用不太常见的运算符:

 v ^= 1; 

编辑:

要清楚; 我从来没有把这个问题看作是代码高尔夫,只是为了find一个简单的方法来完成这个任务,而不使用任何模糊的技巧,比如运营商的副作用。

由于0是一个false值, 1是一个true值。

 v = (v ? 0 : 1); 

如果你乐于使用false而不是数字

 v = !v; 

或者如果他们必须是数字:

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

v = (v + 1) % 2 ,如果你需要循环更多的值,只需要改变2 (n + 1) 。 假设你需要循环0,1,2只是做v = (v + 1) % 3

你可以写一个函数,并使用它:

v = inv(v)

如果你不在意除1之外的任何可能性:

 v = v ? 0 : 1; 

在上面的例子中,如果v为0,false,undefined或null,v最终将为1。 小心使用这种方法 – 即使v是“hello world”,v也是0。

v = 1 - v ,或者v ^= 1或者v= +!v这样的行都可以完成工作,但是它们构成了我所说的hack。 这些不是漂亮的代码,而是廉价的技巧来达到预期的效果。 1 - v不通信“切换0和1之间的值”。 这使得你的代码不那么富有performance力,并且引入了一个地方(尽pipe是一个小地方),另一个开发者将不得不分析你的代码。

相反,像v = toggle(v)这样的函数能够以最快的速度传达意图。

诚实和math的完整性 – 考虑到这个“答案”的票数)导致我编辑这个答案,我拖延了,因为它只是一个简短的琐碎,而不是“深”任何解释似乎都与目的背道而驰,但是,这些意见明确表示,我应该清楚,以避免误解。

我原来的答案是:

这部分规范的措辞:

如果它是0,我想将其设置为1,否则将其设置为0。

意味着最准确的解决scheme是:

 v = dirac_delta(0,v) 

首先,忏悔:我确实让我的德尔塔function感到困惑。 克罗内克三angular洲本来可以稍微适合一些,但是不像我想要的那样是独立于域的东西(克罗内克三angular洲主要用于整数)。 但我真的不应该使用三angular函数,我应该说:

 v = characteristic_function({0},v) 

让我澄清一下。 回想一下,一个函数是一个三元组(X,Y,f) ,其中XY是集合(分别称为和共 ), f是一个将Y的元素分配给X的每个元素的规则。 我们经常把三元(X,Y,f)写成f:X→ Y。 给定X的一个子集,比如A ,有一个特征函数是一个函数x A :X→ {0,1} (它也可以被认为是一个更大的共域的函数,如ℕ或ℝ)。 该function由规则定义:

χA(x)= 1 if x∈ AχA(x)= 0,如果x∉A

如果您喜欢真值表,那么问题是“ X的元素x是子集A的元素吗?”的真值表。

所以从这个定义可以看出,特征函数就是这里所需要的,其中一些大的集合包含0和A = {0} 。 这是我应该写的。

所以三angular洲function。 为此,我们需要了解整合。 要么你已经知道,要么你不知道。 如果你不这样做,我在这里可以说的任何东西都不会告诉你这个理论的错综复杂,但是我可以给出一个句子的总结。 对于集合X的一个度量本质上是“使平均值工作所需要的”。 也就是说,如果我们有一个集合X和一个度量μ ,那么就有一类函数X→ ℝ ,称为可测函数 ,其expression式∫X fdμ有意义,在某种模糊的意义上,是X上f的“平均”。

给定一个集合的度量,可以为该集合的子集定义一个“度量”。 这是通过分配一个子集的特征函数的积分来完成的(假设这是一个可测量的函数)。 这可以是无限的, 也可以是未定义的(两者有微妙的差别)。

有很多措施,但有两个在这里很重要。 一个是真正的标准措施 ,Ropf ;. 对于这个测量,那么ℝ fdμ几乎是你在学校所教的东西(微积分仍然在学校教授?):总结一些小的矩形,并采取越来越小的宽度。 在这个测量中,间隔的量度是它的宽度。 一个点的度量是0。

另一个重要的措施, 任何一套工作,被称为点的措施 。 它被定义为使得函数的积分是其值的总和

∫X fdμ=Σx ∈ X f(x)

这个度量为每个单独的集合赋值1。这意味着一个子集具有有限的度量当且仅当它本身是有限的。 很less有function有限积分。 如果一个函数有一个有限的积分,只有在数的点数上它必须是非零的。 所以你可能知道的绝大多数函数在这个度量下没有有限的积分。

而现在三angular洲的function。 我们来定义一个非常广泛的定义。 我们有一个可测量的空间(X,μ) (所以这是一个测量集合)和一个元素a∈ X。 我们将delta函数 (取决于a )定义为“函数” δa:X→ ℝ 如果x≠a∫Xδadμ= 1,则具有 δa (x)= 0 性质

关于这一点最重要的事实是:delta函数不一定是一个函数 。 它没有被正确定义:我没有说过δa(a)是什么。

你现在做什么取决于你是谁。 这里的世界分为两类。 如果你是math家,你可以这样说:

好的,delta函数可能没有定义。 让我们来看看它的假设性质,看看我们是否能find一个适合它的地方。 我们可以做到这一点,我们最终分配 。 这些不是 (必然的)function,而是有些function的东西,我们经常可以像function一样工作; 但是有一些他们没有的东西(比如“价值”),所以我们需要小心。

如果你不是math家,你可以这样说:

好的,delta函数可能没有正确定义。 谁说的? 一群math家? 别理他们! 他们知道什么?

现在冒犯了我的听众,我会继续。

狄拉克三angular洲通常被认为是一个点(通常为0)的真实线上的三angular函数。 所以那些在评论中抱怨我不知道我的三angular洲的人是这样做的,因为他们正在使用这个定义。 对他们来说,我很抱歉,尽pipe我可以用math家的辩护 (正如Humpty Dumpty所推崇的那样:简单地重新定义一切,使它是正确的)来避免这种情况,但用标准术语来表示不同的东西是不好的forms。

但有一个三angular函数做我想做的事情,而这正是我需要的。 如果我对一个集合X采取一个点测度 ,那么存在一个真正的函数δa:X→ ℝ 它满足delta函数的标准。 这是因为我们正在寻找一个函数X→ ℝ 除了在a和它的所有值的总和是1之外,它是零。这样一个函数很简单:唯一缺less的信息是它的值在a处 ,为了得到总和为1,我们只给它赋值值是1.这就是{a}上的特征函数。 然后:

∫Xδadμ=Σx ∈ Xδa(x)=δa(a)= 1。

所以在这种情况下,对于一个单独的集合,特征函数和δ函数是一致的。

总之,这里有三个“职能”家族:

  1. 单身人士套装的特色function,
  2. 三angular函数,
  3. 克罗内克三angular函数。

其中第二个是最一般的,因为任何其他的都是使用点测度的一个例子。 但是第一和第三的优点是它们总是真正的function。 第三个实际上是第一个特殊情况,对于一个特定的域(整数或其子集)。

所以,最后,当我最初写这个答案的时候,我没有正确地思考(我不想说我很困惑 ,因为我希望我已经certificate了我知道我在说什么时候我其实首先想到的,我只是没有想太多)。 狄拉克三angular洲的通常意义不是这里所要求的,但我的答案的一点是,input域没有被定义,所以克罗内克三angular洲也不会是正确的。 因此,最好的math答案(我所瞄准的)将是特征函数。

我希望这一切都清楚。 而且我也希望我再也不用使用HTML实体来代替TeXmacros来编写一个math片段!

你可以做

 v = Math.abs(--v); 

递减将值设置为0或-1,然后Math.abs将-1转换为+1。

如果它必须是整数1或0,那么你这样做的方式是好的,尽pipe括号是不需要的。 如果这些a被用作布尔值,那么你可以这样做:

 v = !v; 

一般情况下,无论何时需要在两个值之间切换时,都可以从两个切换值的总和中减去当前值:

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

足够 !

总结另一个答案,一个评论和我自己的意见,我build议结合两件事情:

  1. 使用切换function
  2. 在这个函数里面使用一个更可读的实现

这里是你可以放在一个库中的函数,也可以把它包装在另一个Javascript框架的插件中。

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

用法很简单:

 v = inv(v); 

优点是:

  1. 没有代码复制
  2. 如果您或将来再次阅读此内容,您将会在最短的时间内了解您的代码。

解决scheme列表

我想提出三个解决scheme。 他们都将任何值转换为0 (如果1true等)或1 (如果0falsenull ):

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

和另外一个,已经提到,但聪明和快速(虽然只适用于0秒和1秒):

  • v = 1-v

解决scheme1

您可以使用以下解决scheme:

 v = 1*!v 

这将首先将整数转换为相反的布尔值( 0True ,其他任何值为False ),然后将其作为整数乘以1 。 结果0将被转换为1 ,其他任何值都将被转换为0

作为certificate,看看这个jsfiddle并提供你想testing的任何值: jsfiddle.net/rH3g5/

结果如下:

  • -123将转换为整数0
  • -10将转换为整数0
  • -1将转换为整数0
  • 0将转换为整数1
  • 1将转换为整数0
  • 2将转换为整数0
  • 60将转换为整数0

解决scheme2

正如mblase75指出的那样,jAndy有一些其他解决scheme可以像我一样工作:

 v = +!v 

它也首先使原始值为布尔值,但使用+而不是1*将其转换为整数。 结果是完全一样的,但是符号更短。

解决scheme3

另一种方法是使用~~运算符:

 v = ~~!v 

这是非常罕见的,总是从布尔转换为整数。

我不知道你为什么要build立自己的布尔值? 我喜欢时髦的语法,但为什么不写可理解的代码?

这不是最短/最快的,但是最清楚的(每个人都可读)正在使用众所周知的if / else状态:

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

如果你想清楚,你应该使用布尔值而不是数字。 他们对大多数情况下足够快。 有了布尔types,你可以使用这个语法,

 v = !v; 

您原有解决scheme的另一种forms:

 v = Number(v == 0); 

编辑:感谢TehShrike和Guffa指出我原来的解决scheme中的错误。

我会更明确地说。

v是什么意思?

例如,当v是某种状态。 创build一个对象状态。 在DDD中是一个值对象。

在这个值对象中实现逻辑。 然后你可以用更可读的方式编写代码。 切换状态可以通过根据当前状态创build一个新的状态来完成。 你的if语句/逻辑然后被封装在你的对象中,你可以unit testing。 一个valueObject总是不变的,所以它没有身份。 所以要改变它的价值,你必须创造一个新的。

例:

 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); 

另一种方法来做到这一点:

 v = ~(v|-v) >>> 31; 

只需要踢: v = Math.pow(v-1,v)也可以在1和0之间切换。

这是缺less的:

 v = [1, 0][v]; 

它也像循环一样工作:

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

要么

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

最后一个解决scheme的魅力,它也适用于所有其他值。

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

再一个: v=++v%2

(在C中就是简单的++v%=2

PS。 是的,我知道这是双重任务,但这只是C的方法的原始重写(它不工作,导致JS预增加算子不返回左值。

如果你保证你的input是1或0,那么你可以使用:

 v = 2+~v; 

定义一个数组{1,0},将v设置为v [v],因此v的值为0变成1,反之亦然。

既然这是JavaScript,我们可以使用一元+转换为int:

 v = +!v; 

这将逻辑NOT v的值(如果v == 0 ,则返回false如果v == 1 false )。 Then we convert the returned boolean value into its corresponding integer representation.

Another creative way of doing it, with v being equal to any value, will always return 0 or 1

 v = !!v^1; 

If possible values for v are only 0 and 1, then for any integer x, the expression: v = Math.pow((Math.pow(x, v) – x), v); will toggle the value.

I know this is an ugly solution and the OP was not looking for this…but I was thinking about just another solution when I was in the loo 😛

 v=!v; 

will work for v=0 and v=1; and toggle the state;

Untested, but if you're after a boolean I think var v = !v will work.

Reference: http://www.jackfranklin.co.uk/blog/2011/05/a-better-way-to-reverse-variables

If there are just two values, as in this case(0, 1), i believe it's wasteful to use int. Rather go for boolean and work in bits. I know I'm assuming but in case of toggle between two states boolean seems to be ideal choice.

Well, As we know that in javascript only that Boolean comparison will also give you expected result.

ie v = v == 0 is enough for that.

Below is the code for that:

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

multiplying by 1 to turn boolean into number

Interesting Posts