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

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

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

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

Можете ли вы улучшить это?

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

Ответ 1

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

v = 1 - v;

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

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

v ^= 1;

Edit:

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

Ответ 2

Так как 0 - это значение false, а 1 - значение true.

v = (v ? 0 : 1);

Если вы счастливы использовать true и false вместо чисел

v = !v;

или если они должны быть цифрами:

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

Ответ 3

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

Ответ 4

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

v = inv(v)

Ответ 5

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

v = v ? 0 : 1;

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

Ответ 6

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

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

Ответ 7

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

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

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

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

означает, что наиболее точное решение:

v = dirac_delta(0,v)

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

v = characteristic_function({0},v)

Позвольте мне пояснить. Напомним, что функция представляет собой тройку (X, Y, f), где X и Y - множества (называемые соответственно областью и кодомаменом), а f является правилом, которое присваивает элементу Y каждому элементу X. Мы часто пишем тройка (X, Y, f) как f: X & rightarrow; Y. Для подмножества X, скажем A, существует характеристическая функция, являющаяся функцией & chi; A: X & rightarrow; {0,1} (его можно также рассматривать как функцию более крупного кодомена, такого как & Nopf; или & Ropf;). Эта функция определяется правилом:

& chi; A (x) = 1, если x & in; A и & chi; A (x) = 0, если x & notin; А.

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

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

Итак, для дельта-функций. Для этого нам нужно знать об интеграции. Либо вы уже знаете это, либо нет. Если вы этого не сделаете, я ничего не могу сказать здесь, расскажу вам о тонкостях теории, но я могу дать резюме предложения. Мера на множестве X является по существу "тем, что необходимо для усреднения средних". То есть, если мы имеем множество X и меру & mu; на этом множестве существует класс функций X & rightarrow; & Ropf;, называемые измеримыми функциями, для которых выражение & int; X f d & mu; имеет смысл и в каком-то неопределенном смысле имеет "среднее" значение f над X.

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

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

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

& int; X f d & mu; = & sum; x & in; X f (x)

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

И теперь к дельта-функциям. Давайте рассмотрим очень широкое определение. У нас есть измеримое пространство (X, & mu;) (так что множество с мерой на нем) и элемент a & in; X. Мы определяем дельта-функцию (в зависимости от а) как "функцию" a: X & rightarrow; & Ropf; с тем свойством, что a (x) = 0, если x & ne; a и & int; X & delta; a d & mu; = 1.

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

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

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

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

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

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

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

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

& int; X & delta; a d & mu; = & sum; x & in; X & delta; a (x) = & delta; a (a) = 1.

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

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

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

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

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

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

Ответ 8

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

v = Math.abs(--v);

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

Ответ 9

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

v = !v;

Ответ 10

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

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

Ответ 11

v = v == 0 ? 1 : 0;

Достаточно!

Ответ 12

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

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

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

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

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

v = inv(v);

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

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

Ответ 13

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

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

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

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

  • 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

Это довольно необычно и всегда преобразуется в целое число из boolean.

Ответ 14

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

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

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

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

v = !v;

Ответ 15

Другая форма вашего оригинального решения:

v = Number(v == 0);

EDIT: Спасибо TehShrike и Guffa за указание ошибки в моем первоначальном решении.

Ответ 16

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

Что означает v?

Например, когда v - некоторое состояние. Создать статус объекта. В 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);

Ответ 17

Другой способ сделать это:

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

Ответ 18

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

Ответ 19

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

v = [1, 0][v];

Он также работает как круглый 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];

Ответ 20

Еще одно: v=++v%2

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

пс. Да, я знаю, что это двойное назначение, но это просто необработанная переработка метода С (который не работает так, как есть, заставляет JS пред-инкремент оператора dosen't return lvalue.

Ответ 21

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

v = 2+~v;

Ответ 22

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

Ответ 23

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

v = +!v;

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

Ответ 24

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

v = !!v^1;

Ответ 25

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

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

Ответ 26

v=!v;

будет работать для v = 0 и v = 1; и переключить состояние;

Ответ 28

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

Ответ 29

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

то есть. 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);

Ответ 30

v = !v * 1

умножая на 1, чтобы перевести boolean в число