我想在0和1之间切换一个变量。如果是0,我就设它为1,如果是1,我就设它为0。

这是一个非常基本的运算,我经常写,我想研究一下最短,最清晰的方法。这是我目前为止最好的:

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

你能改进一下吗?

编辑:这个问题问的是如何在保持清晰的情况下用最少的字符写出上面的语句——为什么这“不是一个真正的问题”?这并不是一个代码-高尔夫练习,尽管一些有趣的答案来自于把它当作高尔夫的人——很高兴看到高尔夫以一种建设性和发人深省的方式被使用。


v = v == 0 ? 1 : 0;

够了!


你可以为它写一个函数,并像这样使用它:

v = inv(v)


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

v = !v;

如果你不关心除1以外的任何可能性

v = v ? 0 : 1;

在上述情况下,如果v为0、false、undefined或null, v将最终为1。注意使用这种方法-即使v是"hello world", v也将为0。


因为0是一个假值,1是一个真值。

v = (v ? 0 : 1);

如果你喜欢用真和假来代替数字

v = !v;

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

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

你可以简单地使用:

v = 1 - v;

当然,这是假设变量初始化正确,即它只有值0或1。

另一种方法更短,但使用了不太常见的操作符:

v ^= 1;

编辑:

清楚:清楚;我从来没有把这个问题作为代码高尔夫来处理,只是为了找到一种不使用任何模糊技巧(如操作符的副作用)的简单方法来完成任务。


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


你可以这样做

v = Math.abs(--v);

自减式将值设置为0或-1,然后Math。Abs将-1转换为+1。


比如v= 1 - v,或者v ^= 1或者v= +!v都能完成工作,但它们构成了我所说的黑客。这些不是漂亮的代码行,而是达到预期效果的廉价技巧。1 - v不传达“在0和1之间切换值”。这会降低代码的表现力,并引入一个地方(尽管很小),另一个开发人员将不得不解析您的代码。

相反,使用v = toggle(v)这样的函数可以快速传达意图。


另一种创造性的方法是,v等于任何值,总是返回0或1

v = !!v^1;

另一种形式的原始解决方案:

v = Number(v == 0);

编辑:感谢TehShrike和Guffa指出了我最初解决方案中的错误。


一个: v = + + v % 2

(在C语言中是简单的++v%=2)

ps.是的,我知道这是双赋值,但这只是C的方法的原始重写(它不工作,因为JS的前增量操作符不返回左值。


为了总结另一个答案,一个评论和我自己的观点,我建议结合两件事:

使用一个函数进行切换 在这个函数中使用一个可读性更好的实现

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

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

用法很简单:

v = inv(v);

优点是:

无代码复制 如果您或任何人将来再次阅读这篇文章,您将在最短的时间内理解您的代码。


我不知道你为什么要建立你自己的布尔值?我喜欢时髦的语法,但为什么不编写易懂的代码呢?

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

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

如果你想更清楚,你应该使用布尔值而不是数字。在大多数情况下,它们足够快。对于布尔值,你可以使用这样的语法,它将在简短中获胜:

v = !v;

(诚实和数学上的完整性——考虑到这个“答案”的投票数量——促使我编辑了这个答案。我尽可能长时间地拖延,因为这是一个简短的讽刺,而不是任何“深刻”的东西,所以任何解释似乎都与目的背道而驰。然而,这些评论清楚地表明,我应该清楚地避免误解。)

我最初的回答是:

这部分规范的措辞:

如果是0,就设为1,否则设为0。

这意味着最准确的解是:

v = dirac_delta(0,v)

首先,坦白:我的确把函数搞混了。Kronecker delta可能会稍微更合适一些,但并不像我想要的那样是域独立的(Kronecker delta主要用于整数)。但我真的不应该用函数,我应该说

v = characteristic_function({0},v)

让我澄清一下。回想一下,一个函数是一个三重,(X, Y, f), X和Y是集(称为域和域分别)和f是一个规则分配一个元素的X Y的每个元素我们经常写三重f (X, Y, f): X Y→X的一个子集,说,有一个特征函数是一个函数χ:X→{0,1}(它也可以被认为是一个函数的一个更大的上域ℕ或ℝ等)。该函数由如下规则定义:

如果x∈A,则χA(x) = 1;如果x≠A,则χA(x) = 0。

如果你喜欢真值表,它是关于" x的元素x是子集A的元素吗?"的真值表。

根据这个定义,很明显,特征函数是这里所需要的,X是一个包含0和A ={0}的大集合。这是我应该写的。

And so to delta functions. For this, we need to know about integration. Either you already know it, or you don't. If you don't, nothing I can say here will tell you about the intricacies of the theory, but I can give a one sentence summary. A measure on a set X is in essence "that which is needed to make averages work". That is to say that if we have a set X and a measure μ on that set then there is a class of functions X → ℝ, called measurable functions for which the expression ∫X f dμ makes sense and is, in some vague sense, the "average" of f over X.

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

有很多衡量标准,但这里有两个是重要的。一个是真实线上的标准测量,ℝ。对于这个方法,∫ℝf dμ和你在学校里学到的差不多(学校里还教微积分吗?):把小矩形加起来,取越来越小的宽度。在这个度量中,间隔的度量是它的宽度。点的度数是0。

另一个重要的度量,它适用于任何集合,叫做点度量。它的定义是函数的积分是其值的和:

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

这个度量值分配给每个单例集度量值1。这意味着当且仅当一个子集本身是有限的时,它的测度是有限的。很少有函数的积分是有限的。如果一个函数有一个有限积分,它必须只有在可数的点上非零。所以你们可能知道的绝大多数函数在这种方法下都没有有限积分。

现在来看函数。让我们用一个非常宽泛的定义。我们有一个可测量空间(X,μ)(这是一个有测度的集合)和一个元素a∈X。我们“定义”δ函数(取决于a)为“函数”δa: X→ℝ,如果X≠a,∫X δa dμ = 1,则δa(X) = 0。

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

在这一点上你做什么取决于你是谁。这里的世界分为两类。如果你是数学家,你会这样说:

所以函数可能没有定义。让我们来看看它的假设性质,看看我们能否为它找到一个合适的归宿。我们可以这样做,最后得到分布。它们(不一定)是函数,但它们的行为有点像函数,我们经常可以把它们当作函数来处理;但有些东西是他们不具备的(比如“价值观”),所以我们需要小心。

如果你不是数学家,你会这样说:

所以函数可能没有正确定义。谁这么说的?一群数学家?忽略他们!他们知道什么?

既然冒犯了我的听众,我将继续。

狄拉克函数通常被认为是实线上一个点(通常为0)与其标准测度的函数。所以那些在评论中抱怨我不知道我的delta的人这样做是因为他们使用了这个定义。对他们,我要道歉:尽管我可以用数学家的辩护(正如《矮胖子》(Humpty Dumpty)推广的那样:简单地重新定义所有东西,让它是正确的)来回避这一点,但用一个标准术语来指代不同的东西是不礼貌的。

But there is a delta function which does do what I want it to do and it is that which I need here. If I take a point measure on a set X then there is a genuine function δa : X → ℝ which satisfies the criteria for a delta function. This is because we are looking for a function X → ℝ which is zero except at a and such that the sum of all of its values is 1. Such a function is simple: the only missing piece of information is its value at a, and to get the sum to be 1 we just assign it the value 1. This is none other than the characteristic function on {a}. Then:

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

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

总之,这里有三种“函数”:

单例集的特征函数, 函数, 克罗内克函数。

其中第二个是最普遍的,因为其他任何一个都是使用点测量时的一个例子。但第一个和第三个的优点是它们总是真正的函数。第三种实际上是第一种的特殊情况,适用于一组特定的域(整数或其某个子集)。

So, finally, when I originally wrote the answer I wasn't thinking properly (I wouldn't go so far as to say that I was confused, as I hope I've just demonstrated I do know what I'm talking about when I actually think first, I just didn't think very much). The usual meaning of the dirac delta is not what is wanted here, but one of the points of my answer was that the input domain was not defined so the Kronecker delta would also not have been right. Thus the best mathematical answer (which I was aiming for) would have been the characteristic function.

我希望大家都明白了;我也希望我再也不用用HTML实体而不是TeX宏来写一篇数学文章!


未经测试,但如果你是布尔,我认为var v = !v将工作。

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


一般来说,当你需要在两个值之间切换时,你可以从两个切换值的和中减去当前值:

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


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

v = 2+~v;

我会说得更清楚一点。

v是什么意思?

例如v是某种状态。创建对象Status。在DDD中是一个值对象。

在这个值对象中实现逻辑。这样你就可以以更实用的方式编写代码,从而更易于阅读。切换状态可以在当前状态的基础上创建一个新的status。然后,你的if语句/逻辑被封装在你的对象中,你可以单元测试。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的可能值只有0和1,那么对于任意整数x,表达式为: v = Math.pow((Math。Pow (x, v) - x), v); 将切换该值。

我知道这是一个丑陋的解决方案,而且OP并没有想要这个…但我在厕所的时候想到了另一个解决方案:P


解决方案列表

我想提出三个解决方案。它们都将任何值转换为0(如果1,true等)或1(如果0,false, null等):

V = 1*!v V = +!v V = ~~!v

还有一个额外的,已经提到过,但聪明和快速(虽然只适用于0和1):

V = 1-v

解决方案1

您可以使用以下解决方案:

v = 1*!v

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

作为证明,请参阅这个jsfiddle并提供您希望测试的任何值:jsfiddle.net/rH3g5/

结果如下:

-123将转换为整数0, -10将转换为整数0, -1将转换为整数0, 0会转换成整数1, 1会转换成整数0, 2会转换成整数0, 60会转换成整数0,

解决方案2

正如mblase75指出,jAndy有一些其他的解决方案,作为我的工作:

v = +!v

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

解决方案3

另一种方法是使用~~操作符:

v = ~~!v

它非常不常见,总是从布尔值转换为整数。


另一种说法是:

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

只是为了好玩:v = Math.pow(v-1,v)也在1和0之间切换。


v=!v;

对于v=0和v=1都成立;切换状态;


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


如果只有两个值,如本例中的(0,1),我认为使用int是浪费的。宁愿用布尔值,用比特来计算。我知道我在假设,但在两种状态之间切换布尔似乎是理想的选择。


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

v = +!v;

这将在逻辑上不是v的值(如果v == 0则为真,如果v == 1则为假)。然后我们将返回的布尔值转换为相应的整数表示。


这是缺失的:

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

Or

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

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

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

对于一个非常特殊的情况,比如获取一个(变化的)值并且未定义,这个模式可能是有用的:

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

好吧,我们知道在javascript中只有布尔比较也会给你预期的结果。

比如v = v = 0就足够了。

下面是它的代码:

Var v = 0; Alert ("if v = 0 output: " + (v == 0)); setTimeout(函数(){ V = 1; alert("if v = 1 Output: " + (v == 0)); }, 1000);

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

希望这对你有所帮助:)


v = !v * 1

乘以1将布尔值转换为数字


v = Number(!v)

它将反向布尔值类型转换为Number,这是期望的输出。