Есть ли лучший способ записи v = (v == 0? 1: 0); [закрыто]


465

Я хочу переключить переменную между 0 и 1. Если это 0, я хочу установить 1, иначе, если это 1, я хочу установить 0.

Это настолько фундаментальная операция, что я пишу так часто, что мне хотелось бы исследовать самый короткий и ясный способ ее выполнения. Вот мой лучший пока:

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

Вы можете улучшить это?

Изменить: вопрос заключается в том, как написать вышеупомянутое утверждение с наименьшим количеством символов при сохранении ясности - как это «не реальный вопрос»? Это не было задумано как упражнение по коду для гольфа, хотя некоторые интересные ответы были получены от людей, относящихся к нему как к гольфу - приятно видеть, что гольф используется конструктивно и заставляет задуматься.


20
Это выглядит уже просто / ясно / коротко для меня.
Моб

136
обман:v = +!v;
jAndy

48
Если «лучше» также означает «быстрее»: jsperf.com/v-0-1-0 .
pimvdb

7
@Mobinga: +1. Это так просто, как и должно быть. Все остальные ответы, которые я вижу, сбивают с толку, и некоторые из них меняют логику; представляя ошибки.
Ян Бойд

8
@holodoc Лучшим решением для выражения своего мнения будет создание ответа, в котором говорится, что вы считаете, что оригинал является лучшим способом, и подробное описание ПОЧЕМУ, по вашему мнению, именно так. это также позволяет другим людям легко поддержать ваш ответ, проголосовав за него.
Чак ван дер Линден

Ответы:


721

Вы можете просто использовать:

v = 1 - v;

Это, конечно, предполагает, что переменная инициализирована должным образом, то есть имеет значение 0 или 1.

Другой метод, который короче, но использует менее распространенный оператор:

v ^= 1;

Редактировать:

Быть понятным; Я никогда не подходил к этому вопросу как к кодовому гольфу, просто чтобы найти краткий способ решения этой задачи, не используя никаких скрывающих приемов, таких как побочные эффекты операторов.


206
Это красивые строки кода, как мелко нарезанное стекло или редкие цветущие орхидеи. Мне нравится, что вы достигли прямого уровня логического слоя и напрямую справились с математикой 1 и 0 с наиболее оптимальными операциями из возможных. Я буду использовать их в своих собственных проектах, но, к сожалению, когда мне понадобится понять код коллегам, мне придется по умолчанию использовать более логичный подход. Спасибо, хотя, ваш ответ сделал мой день.
Олли Гласс

37
Вы всегда можете добавить комментарий о том, что делает код.
Prusse

25
@ Кевин: это не правда, что это явно не отвечает на вопрос, как задано. Вопрос сказал: «Я хочу переключить переменную между 0 и 1». Очень разумная интерпретация заключается в том, что это означает, что значение переменной уже равно 0 или 1. Эта интерпретация / ограничение была явно указана в ответе. На что в мире вы можете возразить?
LarsH

50
@ Матфей, ​​чтобы сказать, что тот, кто не понимает, v ^= 1должен прекратить программировать, немного резок, я думаю. Как было сказано ранее, это не один из наиболее распространенных операторов, и он не делает то же самое, что и v = v ^ 1. Также оператор означает что-то совершенно другое на разных языках (VB). Да, быстрый просмотр скажет вам, что это оператор XOR, и вы поймете, что он делает, но для многих это может быть неочевидно на первый взгляд. Я не думаю, что это означает, что вам нужно бросить свою работу.
Джей Ди Айзекс

80
Если вы сохраните 15 символов, написав это, но затем используйте 40 символов комментариев, чтобы объяснить это, действительно ли это улучшение?
Майкл Майерс

343

Так 0как является falseзначением и 1является trueзначением.

v = (v ? 0 : 1);

Если вы с удовольствием используете trueи falseвместо цифр

v = !v;

или если они должны быть числами:

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

55
просто положи магию +перед этим !. Оооо это выглядит так грязно! но круто: p
jAndy

1
@Quentin - это нарушит код парня, если у него есть switch(v){ case 0 ...или если (v == 0) или если v === 0. Вы меняете его результат в дополнение к его подходу ...
Брайан

34
Сделай из этого смайлик ({v :+! v}).v.
pimvdb

17
@ Брайан: не с этим волшебным +знаком! ¯ \ _ (ツ) _ / ¯
jAndy

11
+1 за v = (v ? 0 : 1)понятный и идиоматичный JS.
Беннет МакЭлви

200

v = (v + 1) % 2и если вам нужно перебрать больше значений, просто измените 2на (n + 1). Скажем, вам нужно цикл 0,1,2 просто сделать v = (v + 1) % 3.


2
Я люблю цикл! Это действительно умно.
Олли Гласс

16
+1 за размышление о переключении как цикле. Просто, учитывая, насколько это гибко.
Гуффа

3
+1 за предоставление модульного решения, которое также является надежным. На практике вы, вероятно, захотите использовать constпеременную вместо магических чисел 2, 3, ...
oosterwal

2
Более короткий (хакерский) способ: ++v % 3если вы хотите перебрать 0, 1, 2
haraldmartin

75

Вы можете написать для него функцию и использовать ее следующим образом:

v = inv(v)


30
+1 Я полностью согласен, что это самое чистое решение (... но что потом входит в invфункцию: P)
Леа Хейс,

4
Я хотел бы дать этот ответ больше, чем просто +1. Если общий код не является ослепительно очевидным, он должен быть заключен в функцию с описательным именем.
ТехШрик

11
@TehShrike вы считаете invописательным именем?
Беннет МакЭлви

3
@Bennett McElwee: inv = инвертировать. Мне всегда казалось, что это обычное сокращение.
Даниэль

51
Зачем сокращать его тогда, назовите его «инвертировать» или «переключать», и код должен быть читабельным. это не так, как будто мы пытаемся поместить этот материал в перфокарту с 80 столбцами или что-то в этом роде.
Чак ван дер Линден

50

Если вас не волнует какая-либо возможность, кроме 1:

v = v ? 0 : 1;

В приведенном выше случае v будет равен 1, если v равно 0, false, undefined или null. Будьте осторожны, используя такой подход - v будет 0, даже если v "привет мир".


2
Это не перевернет значение. Вы имеете в виду v = v ? 0 : 1.
Гуффа

3
@ Гуффа - +1 за то, что я заболела дислексией ...
Брайан,

3
Это мой любимый логический ответ, который я могу использовать с коллегами (я вижу ответ @ Guffa как числовой). Мне нравится, как вы взяли ненужный тест (v == 0) и заключили в скобки, уменьшив его до абсолютного минимального количества символов. Спасибо.
Олли Гласс

1
Я большой поклонник ответа @ Guffa тоже - по словам Линарда Скайнарда, будь простым человеком;)
Брайан

2
+1 за понимание "правдивых" ценностей.
zzzzBov

44

Линии вроде v = 1 - v, или v ^= 1или v= +!vвсе выполнят работу, но они составляют то, что я бы назвал хаки. Это не красивые строки кода, а дешевые трюки для достижения желаемого эффекта. 1 - vне сообщает "переключить значение между 0 и 1". Это делает ваш код менее выразительным и создает место (пусть и небольшое), где другой разработчик должен будет проанализировать ваш код.

Вместо этого такая функция как бы v = toggle(v)сообщает о намерении с первого взгляда.


8
-1 серьезно, v=1-vне связывает тумблер?
Блинди

22
1-vможет общаться действительно переключаться, но это единственное, что он сообщает. Например, он может также передавать линию с нулем в v=1или зеркальное преобразование с центром в v=0.5. В этом смысле это относительно неоднозначно. Это правда, что знание, которое vможет только когда-либо быть 0или 1ограничивать его предполагаемое значение, но заставляет других разработчиков (или ваше будущее Я) понять этот контекст, прежде чем сможет понять эту простую линию. Вы не можете быть намного яснее, чемv = toggle(v)
Рэй

10
v ^= 1Совершенно ясно, если вы понимаете логические операции, что вам лучше, если вы программист. Я думаю, что это разница между этим и v=1-v; одна - логическая операция, другая - арифметическая, и мы пытаемся представить логическое понятие, а не математическое.
Мэтью Рид

6
@ Matthew Read: Это отличное утверждение, которое хорошо подводит итог моим мыслям: «мы пытаемся представить логическое понятие, а не математическое». Даже v ^= 1есть некоторая двусмысленность, хотя, поскольку это может интерпретироваться как побитовый xor.
Рэй

6
для программистов (и да, я имею в виду таких фанатов, как мы), это вполне понятно. Они не хаки, потому что они изящны благодаря своей простоте.
gion_13

38

( Честность и математическая целостность - учитывая количество голосов по этому «ответу» - заставили меня отредактировать этот ответ. Я задержался как можно дольше, потому что он был задуман как короткое замечание, а не как «глубокий», так что любое объяснение казалось противоречащим цели. Однако комментарии ясно дают понять, что я должен быть ясным, чтобы избежать недоразумений. )

Мой оригинальный ответ:

Формулировка этой части спецификации:

Если это 0, я хочу установить его на 1, иначе установить 0.

подразумевает, что наиболее точным решением является:

v = dirac_delta(0,v)

Во- первых, признание: я сделал , чтобы мои дельта - функции спутать. Дельта Кронекера была бы немного более подходящей, но не намного, поскольку я хотел что-то, что было бы независимым от домена (дельта Кронекера в основном используется только для целых чисел). Но я действительно не должен был использовать дельта-функции вообще, я должен был сказать:

v = characteristic_function({0},v)

Позвольте мне уточнить. Напомним , что функция является тройной, (X, Y, F) , где Х и Y представляют собой наборы ( так называемый домен и кообласть соответственно) и е представляет собой правило , которое присваивает элемент Y к каждому элементу X . Мы часто пишем тройной (X, Y, F) , как F: X → Y . Для некоторого подмножества X , скажем, A , существует характеристическая функция, которая является функцией χ A : X → {0,1}(его также можно рассматривать как функцию для более крупного кодомена, такого как ℕ или ℝ). Эта функция определяется правилом:

χ (х) = 1 , если х ∈ A и χ (х) = 0 , если х ∉ .

Если вам нравятся таблицы истинности, это таблица истинности для вопроса «Является ли элемент x из X элементом подмножества A ?».

Таким образом, из этого определения ясно, что характеристическая функция - это то, что здесь необходимо, с X большим набором, содержащим 0 и A = {0} . Это то, что я должен был написать.

И так с дельта-функциями. Для этого нам нужно знать об интеграции. Либо вы уже это знаете, либо нет. Если вы этого не сделаете, то ничего, что я могу здесь сказать, не расскажет вам о тонкостях теории, но я могу дать краткое изложение одного предложения. Мера на множестве X , в сущности , «то , что нужно , чтобы сделать работу усредняет». То есть, если у нас есть множество X и мера µ на этом множестве, то существует класс функций X → ℝ , называемых измеримыми функциями, для которых выражение X f dμ имеет смысл и, в некотором неопределенном смысле, «среднее» из F над X .

Учитывая меру в наборе, можно определить «меру» для подмножеств этого набора. Это делается путем присвоения подмножеству интеграла его характеристической функции (при условии, что это измеримая функция). Это может быть бесконечным или неопределенным (два слегка различаются).

Есть много мер вокруг, но есть два, которые здесь важны. Одним из них является стандартная мера на реальной линии, ℝ. Для этой меры тогда f dμ - это почти то, чему вас учат в школе (исчисление все еще преподают в школах?): Суммируйте маленькие прямоугольники и выбирайте все меньшую и меньшую ширину. В этой мере мерой интервала является его ширина. Мера точки равна 0.

Другая важная мера, которая работает на любом множестве, называется точечной мерой . Он определяется так, что интеграл функции является суммой ее значений:

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

Эта мера назначает каждому одноэлементному набору меру 1. Это означает, что подмножество имеет конечную меру тогда и только тогда, когда оно само является конечным. И очень немногие функции имеют конечный интеграл. Если функция имеет конечный интеграл, она должна быть ненулевой только на счетном количестве точек. Таким образом, подавляющее большинство функций, которые вы, вероятно, знаете, не имеют конечного интеграла по этой мере.

А теперь к дельта-функциям. Давайте возьмем очень широкое определение. У нас есть измеримое пространство (X, μ) (так что это множество с мерой на нем) и элемент ∈ X . Мы «определяем» дельта-функцию (в зависимости от a ) как «функцию» δ a : X → ℝ со свойством δ a (x) = 0, если x x a и X δ a dμ = 1 .

Самый важный факт, который можно использовать для этого, заключается в следующем: дельта-функция не обязательно должна быть функцией . Это не правильно определено: Я не сказал , что & delta (а) есть.

Что вы делаете в этот момент, зависит от того, кто вы есть. Мир здесь делится на две категории. Если вы математик, вы говорите следующее:

Итак, дельта-функция не может быть определена. Давайте посмотрим на его гипотетических свойств и посмотреть , если мы сможем найти правильный дом для нее , где она будет определена. Мы можем сделать это, и мы в конечном итоге с распределениями . Это не (обязательно) функции, но вещи, которые ведут себя немного как функции, и часто мы можем работать с ними, как если бы они были функциями; но есть определенные вещи, которых у них нет (например, «ценности»), поэтому мы должны быть осторожны.

Если вы не математик, вы говорите следующее:

Итак, дельта-функция может быть неправильно определена. Кто так говорит? Куча математиков? Игнорируй их! Что они знают?

Обидев теперь мою аудиторию, я продолжу.

Дираковская дельта обычно берется дельта - функция точки (часто 0) в реальном соответствии со своей стандартной мерой. Так что те, кто жалуется в комментариях о том, что я не знаю моих дельт, делают это, потому что они используют это определение. Я приношу им свои извинения: хотя я могу выкрутиться из этого, используя защиту Математика (популяризируемую Шалтай-Болтай : просто переопределить все так, чтобы она была правильной), использование стандартного термина для обозначения чего-то другого - это плохая форма.

Но есть дельта - функция , которая делает то , что я хочу, чтобы это сделать , и это то , что мне нужно здесь. Если взять меру точки на множество X , то есть является подлинной функция δ в : X → ℝ , которая удовлетворяет критерии для дельта - функции. Это потому, что мы ищем функцию X → ℝ, которая равна нулю за исключением a и такая, что сумма всех ее значений равна 1. Такая функция проста: единственная недостающая часть информации - это ее значение в a , и чтобы получить сумму, равную 1, мы просто присваиваем ей значение 1. Это не что иное, как характеристическая функция на {a} . Затем:

X δ дМ = Σ х ∈ X , δ (х) = δ (а) = 1.

Таким образом, в этом случае для одноэлементного множества характеристическая функция и дельта-функция совпадают.

В заключение, здесь есть три семейства «функций»:

  1. Характеристические функции одноэлементных множеств,
  2. Дельта-функции,
  3. Дельта-функции Кронекера.

Второй из них является наиболее общим , как любой из других является примером этого при использовании измерения точки. Но первое и третье имеют то преимущество, что они всегда являются подлинными функциями. Третий фактически является частным случаем первого для определенного семейства доменов (целых чисел или некоторого их подмножества).

Таким образом, в конце концов, когда я первоначально написал ответ , который я не думая , правильно (я бы не пошел так далеко, чтобы сказать , что я был смущен , как я надеюсь , что я только что показал , я действительно знаю , что я говорю о том, когда Я действительно сначала думаю, я просто не очень много думал). Обычное значение дельты Дирака здесь не то, что нужно, но один из пунктов моего ответа заключался в том, что входная область не была определена, поэтому дельта Кронекера также была бы неправильной. Таким образом, лучшим математическим ответом (к которому я стремился) была бы характеристическая функция.

Я надеюсь, что это все ясно; и я также надеюсь, что мне больше никогда не придется писать математическую часть, используя объекты HTML вместо макросов TeX!


37
+1 - Если бы я мог понизить голос Квентина за то, что он не знал функцию dirac_delta, я бы сделал это. Я хотел бы знать, в каком колледже он учился, потому что я не думаю, что найму кого-нибудь оттуда, если они даже не знают чего-то, что имеет фундаментальное значение для цифровой обработки. Я хотел бы еще больше понизить Квентин за его неспособность понять юмор, который вы пытались.
Данк

23
Если бы я отрицал каждый ответ, я не понимал ... Я бы отрицал множество ответов.
Симус

4
Привет Андрей, это было давно.
Тим Даун

4
@ Тим: Хорошее горе, так оно и есть! А как поживает епископ Бермудский? (Я правильно помню?) Думаю, эта ветка комментариев не лучшее место, чтобы наверстать упущенное, хотя ... 17 лет, не так ли?
Эндрю Стейси

3
@ Cԃ ա ԃ "Этот ответ не удался ..." вздох . Вы читали, что я математик, не так ли? Этот ответ отлично работает для сферического программиста в вакууме, поэтому я не знаю, на что вы жалуетесь.
Эндрю Стейси

35

Вы могли бы сделать

v = Math.abs(--v);

Уменьшение устанавливает значение в 0 или -1, а затем Math.absпреобразует -1 в +1.


27
Это превратилось в конкурс «Сгенерируйте 10000 способов выполнить простую задачу». И мне нравятся все способы, ха-ха.
Джош

27
v = Math.round(Math.sin(Math.PI/(v+3)));
Бенуа

15
@Benoit - ваша формула равна 1 для v = 0 и v = 1. ЭТО один правильный, хотя! v = Math.round(Math.cos(Math.PI/((v*2+1)+2)-2*v));: D
Teo.sk

2
Это никогда не изменит значение. Если v = 1то v = Math.Abs(-1)что +1. Если v = 0то, v = Math.Abs(-0)что равно 0.
Пол

1
+1 А это был мой второй ... Грр.
рекурсивный

34

в общем, когда вам нужно переключиться между двумя значениями, вы можете просто вычесть текущее значение из суммы двух значений переключения:

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

2
Это интересно и креативно, но потенциально опасно. Если vон поврежден, он внезапно начнет переключаться между двумя различными значениями. (Просто кое-что рассмотреть ...)
oosterwal

1
+1 за интересную идею. не то, чтобы ОП или кто-либо еще фактически использовал его в этих обстоятельствах, но эта информация должна существовать где-то в мозгу вечно.
Шимми Вейцхандлер

3
@oosterwal: Тогда, конечно, проблема заключается в коррупции ...
GManNickG

@GManNickG: Рано или поздно произойдет повреждение данных, поэтому мы должны знать о последствиях его отсутствия. Если vобычно используется для попеременного выполнения двух состояний из списка из трех или более состояний, то повреждение vможет привести к тому, что программа поочередно выполнит два совершенно разных состояния - это может привести к неожиданным и нежелательным результатам. Урок, который можно извлечь из этого: всегда проверяйте достоверность своих данных.
oosterwal

33

Если это должно быть целое число 1 или 0, то то, как вы это делаете, хорошо, хотя скобки не нужны. Если эти a будут использоваться как логические значения, то вы можете просто сделать:

v = !v;

10
не приведет ли это к тому, что для Олли "v" будет задан логический результат, а не целое число?
Брайан

12
Да, будет, и я предупредил, что в предложении над строкой кода. Если эти a будут использоваться как логические значения
Майкл Берковски

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

Достаточно !


7
Больше мнения, чем ответа, тебе не кажется?
Брайан

16
@ Брайан: «лучше» это все о мнении на самом деле.
pimvdb

3
Мне нравится, как вы сняли скобки - это урезает пару символов!
Олли Гласс

9
@ Брайан: « Ответ » - «Нет, лучшего способа написания нет v = (v==0 ? 1 : 0);» . Все остальные находят разные способы игры в гольф; и на самом деле не отвечая на вопрос. Вот почему я проголосовал за этот ответ.
Ян Бойд

19

Список решений

Есть три решения, которые я хотел бы предложить. Все они преобразовать любое значение 0(если 1, и trueт.д.) , или 1(если 0, false, и nullт.д.):

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

и еще один, уже упомянутый, но умный и быстрый (хотя работает только для 0s и 1s):

  • 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

Это довольно редко и всегда конвертируется в целое число от логического.


В JavaScript вы можете использовать префикс переменной, +чтобы преобразовать ее в число, что +!vэквивалентно вашему решению (решение jAndy в комментариях ОП).
Blazemonger

@ mblase75: Да, вы правы, что 1*может быть заменено +при попытке преобразовать логическое значение в целое число. Все остальное в моем ответе остается прежним. Ответ Энди правильный, но мой более подробный. Я добавлю его / ее решение в мой ответ.
Tadeck

@ Тадек +1 за хорошую идею.
Шимми Вайцхандлер

17

Подводя итог другому ответу, комментарию и собственному мнению, я предлагаю объединить две вещи:

  1. Используйте функцию для переключения
  2. Внутри этой функции используйте более читаемую реализацию

Вот функция, которую вы можете поместить в библиотеку или обернуть в плагин для другой Javascript Framework.

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

И использование просто:

v = inv(v);

Преимущества:

  1. Нет дублирования кода
  2. Если вы или кто-либо еще прочитаете это в будущем, вы поймете свой код за минимальное время.

Они? Я провел быстрый тест: jsperf.com/function-vs-no-function/2 и кажется, что разница не так уж велика .
Мартин Шлагнитвейт,

25
7,5 нс против 8,8 нс. Эти дополнительные 1,3 наносекунды действительно убьют вас.
Ян Бойд

5
Со всем, что я сэкономил, я взял свою семью в Мир Диснея! :-)
Том

1
Совершенно верно. Людям, пишущим «умные» решения, вероятно, никогда не приходилось поддерживать «жемчужины» кода других программистов
Avi

1
почему нет function toggle(i){ return i == 0 ? 1 : 0 }?
Билли Мун

13

Я не знаю, почему вы хотите создать свои собственные логические выражения? Мне нравятся прикольные синтаксисы, но почему бы не написать понятный код?

Это не самое короткое / самое быстрое, но самое ясное (и читаемое для всех) использование хорошо известного состояния if / else:

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

Если вы хотите быть действительно понятным, вы должны использовать для этого логические числа вместо цифр. Они достаточно быстры для большинства случаев. С логическими значениями вы можете просто использовать этот синтаксис, который выиграет в краткости:

v = !v;

1
Это был бы мой предпочтительный ответ; но троичный оператор против if-else - священная война, я не хотел зажигать взрыватель. Тем не менее, я думаю, что первая строка должна быть === 0. При вводе выборки 7правильный вывод - 0это вывод 1.
Ян Бойд

4
Есть ли смысл молча исправлять ввод, такой как 7, вместо того, чтобы выдавать какое-то исключение? Я имею в виду, что если какой-то другой фрагмент кода попал в руки 7, когда ожидал только 0 или 1, прежде чем ваш код исправил значение?
Чак ван дер Линден

12

Еще одна форма вашего оригинального решения:

v = Number(v == 0);

РЕДАКТИРОВАТЬ: Спасибо TehShrike и Guffa за указание на ошибку в моем первоначальном решении.


4
Оператор == возвращает логическое значение (вместо целого числа) во многих системах. Это работало бы, только если v было определено как целое число, и язык был крут с автоматическим приведением от логического к целому числу.
ТехШрик

Очень верно. Я отвечал на вопрос в контексте JavaScript (как вопрос был помечен).
Курт Кейлор

@Kurt Kaylor: Javascript - это одна из систем, где оператор == возвращает логическое значение, поэтому он не выполняет то же самое, что и исходное решение.
Гуффа

@Guffa: я использую тот факт, что javascript - это слабо типизированный язык с неявным преобразованием типов (например, '0.0000 '== 0, 0 == "", false == "", false == 0, 1 == правда и тд). Я могу использовать возвращенное логическое значение так же, как могу использовать целое число со значением 0 или 1. Попробуйте, например, оценить «2 + true» в консоли javascript, вы получите 3.
Курт Кейлор

1
@ Kurt Kaylor: Это работает только в ситуациях, когда вы форсируете неявное преобразование. Попробуйте, например, 'opacity:'+trueи вы получите opacity:trueвместо opacity:1.
Гуффа

11

Я бы сделал это более явным.

Что vзначит?

Например, когда v некоторое состояние. Создать объект Status. В DDD объект значения.

Реализуйте логику в этом объекте значения. Тогда вы можете написать свой код более функциональным способом, который будет более читабельным. Переключение статуса может быть сделано путем создания нового статуса на основе текущего статуса. Ваша инструкция / логика 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);

6
над разработкой?
alejandro5042

6
+1 за то, что заставил меня смеяться
Denshi


10

Это отсутствует:

v = [1, 0][v];

Он также работает как Round 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 ...

Или

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

Прелесть последнего решения, оно работает и со всеми другими ценностями.

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

Для очень особого случая, например, для получения (изменяющегося) значения undefined, этот шаблон может быть полезен:

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

9

Поскольку это JavaScript, мы можем использовать унарный +для преобразования в int:

v = +!v;

Это будет логическое NOTзначение v(давая, trueесли v == 0или falseесли v == 1). Затем мы конвертируем возвращенное логическое значение в соответствующее целочисленное представление.


8

Только для ударов: v = Math.pow(v-1,v)также переключается между 1 и 0.


7

Еще: v=++v%2

(в С было бы просто ++v%=2)

пс. Да, я знаю, что это двойное присваивание, но это просто необработанное переписывание метода Си (который не работает как есть, потому что оператор предварительного приращения JS не возвращает lvalue.


3
Ваша версия C нелегальна; Вы не можете изменить результат ++оператора (это не lvalue). Что касается v=++v%2, вы модифицируете vдважды. Я не знаю, хорошо ли это определено в JavaScript, но это не обязательно. v = (v+1) % 2,
Кит Томпсон

По крайней мере, так c++оно и есть - потому что оператор предварительного увеличения имеет более высокий приоритет и изменяет переменную «на месте», поэтому его можно использовать как lvalue. Я думаю, что реализация JS ++такова, что она не может рассматриваться как lvalue: / Да, это избыточно, но я пытался показать только другой метод - уже есть лучшие решения :)
Адам Jurczyk

3
+1. Может быть записано как v = (v + 1)% 2.
niktrs

7

Если вы уверены, что ваш ввод 1 или 0, то вы можете использовать:

v = 2+~v;

7

определить массив {1,0}, установить v в v [v], поэтому v со значением 0 становится 1, и наоборот.


Мое решение правильное, если вам не нравится, напишите почему. Ваш комментарий никому не помогает. Мое решение читает переменную, в отличие от принятия решения. Это требует меньше ресурсов процессора.
S ..

5

Другой творческий способ сделать это, vравный любому значению, всегда вернет 0или1

v = !!v^1;

3
два !!результата ничего не !!!!дают в логической математике, вы можете положить туда и будете такими же, но в результате 4 ненужных операции
Alex K

10
@ Алекс: !!приведёт к булу. !!(1) === trueи!!(0) === false
nickf

1
@nickf: ага, так что, думаю, v = Boolean(v^1)было бы более информативно, спасибо за объяснение - не думал о кастинге
Alex K

1
@ Алекс, "логическая математика"? Вот почему математики плохие программисты. Не пойми меня неправильно; Хорошие программисты также хорошо разбираются в математике. Но это не имеет ничего общего с логической математикой. Это языковая конструкция, которая при любом выражении, по крайней мере в Javascript, !преобразует его в логическое значение. Добавление другого !отменит это логическое значение. Приведение здесь неявно, и конечный результат работает. Там нет необходимости для -1.
Яник Рошон

1
Я совсем не математик. Вы можете попробовать это и увидеть себя jsperf.com/javascript-boolean-test
Alex K

4

Если возможными значениями для v являются только 0 и 1, то для любого целого числа x выражение: v = Math.pow ((Math.pow (x, v) - x), v); будет переключать значение.

Я знаю, что это уродливое решение, и ОП не искал этого ... но я думал о другом решении, когда был в туалете: P




1

Если есть только два значения, как в этом случае (0, 1), я полагаю, что расточительно использовать int. Скорее идите для логического и работать в битах. Я знаю, что предполагаю, но в случае переключения между двумя состояниями логическое значение кажется идеальным выбором.


1

Ну, поскольку мы знаем, что в javascript только это логическое сравнение также даст ожидаемый результат.

т.е. v = v == 0достаточно для этого.

Ниже приведен код для этого:

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/

Надеюсь, это поможет вам :)


Это работает для переключения значения, но значение переключается не между 0 и 1, а между trueи false. Вы можете использовать v == 0для определения значения переменной в условии, но если вы хотите использовать значение 0 или 1, вам нужно будет использовать что-то вроде v == 0 ? 0 : 1или, Number(v)чтобы получить это. (Кроме того, вы можете использовать v = !v;для переключения между trueи false.)
Guffa

да, понял .. спасибо :)
Викаш Пандей

0

v = число (! v)

Он наберет приведенное значение Inverted Boolean в Number, которое является желаемым выходным значением.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.