4 способа обмена значений между переменными в JavaScript

4 способа обмена значений между переменными в JavaScript

От автора: многие алгоритмы требуют обмена значениями между двумя переменными. Во время собеседования по кодированию вас могут спросить: «Как обменять значения между 2 переменными без временной переменной?».

Полезно знать несколько способов обмена значениями между переменными. В этом посте вы прочитаете о 4 способах обмена (2 их которые используют дополнительную память и 2 не используют).

1. Деструктурирующее присваивание

Деструктурирующее присваивание (функция ES2015 ) позволяет извлекать элементы массива в переменные. Например, следующий код деструктурирует массив:

let a;
let b; [a, b] = [1, 2, 3];
a; // => 1
b; // => 2

[a, b] = [1, 2, 3] является деструктурирующим присваиванием, которое деструктурирует массив [1, 2, 3]. Переменной a присваивается первый элемент 1 из [1, 2, 3], соответственно, b присваивается второй элемент 2.

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

let a = 1;
let b = 2; [a, b] = [b, a];
a; // => 2
b; // => 1

[a, b] = является деструктурирующим присваиванием, которое меняет местами значения переменных a и b. На первом этапе, справа от деструктурирования, создается временный массив (который оценивается, как [2, 1]).

После этого происходит деструктурирование временного массива: [a, b] = [2, 1]. Переменной a присваивается 2, и b присваивается 1. Обмен значений a и b был выполнен.

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

Я рекомендую менять значения между переменными с использованием присваивания в большинстве случаев.

2. Временная переменная

Обмен значениями между переменными с использованием временной переменной является классическим. Как следует из названия, этот подход требует дополнительной временной переменной. Давайте поменяем значения между переменными a и b, используя временную переменную temp:

let a = 1;
let b = 2;
let temp; temp = a;a = b;b = temp;
a; // => 2
b; // => 1

Temp — это временная переменная. На первом шаге temp присваивается значение a. Затем переменной a присваивается значение b. Наконец, переменной b присваивается значение temp (имеющей начальное значение a).

Обмен значениями с использованием временной переменной работает с любыми типами значений, такими как числа, строки, логические значения, объекты.

Недостатком этого подхода является необходимость в специальной временной переменной, плюс замена происходит в 3 оператора.

3. Сложение и вычитание

Вы можете обменять значения между переменными без использования дополнительной памяти (например, временного массива или переменной).

В следующем примере переменные a и b меняются значениями, используются арифметические операторы сложения + и вычитания -:

let a = 1;
let b = 2; a = a + b;b = a - b;a = a - b;
a; // => 2
b; // => 1

Изначально a равно 1, а b равно 2. Давайте посмотрим, как выполняется обмен:

a = a + b присваиваем a значение 1 + 2.

b = a – b присваивает b значение 1 + 2 — 2 = 1 (b сейчас равно 1).

a = a – b присваивает a значение 1 + 2 — 1 = 2 (a сейчас равно 2).

В конце у нас a равно 2, а b равно 1. Обмен между a и b выполнен. Хотя этот подход не использует временные переменные, он имеет значительные ограничения.

Во-первых, вы можете поменять местами только целые числа. Во-вторых, помните о лимите при выполнении сложения на первом шаге a = a + b (сумма должна быть меньше, чем Number.MAX_SAFE_INTEGER).

4. Побитовый оператор XOR

Оператор XOR оценивается как true, если операнды отличаются. Как напоминание, вот таблица значений для XOR:

┌─────┬─────┬───────┐
│ a │ b │ a ^ b │
├─────┼─────┼───────┤
│ 0 │ 0 │ 0 │
│ 1 │ 1 │ 0 │
│ 0 │ 1 │ 1 │
│ 1 │ 0 │ 1 │
└─────┴─────┴───────┘

В JavaScript побитовый оператор XOR n1 ^ n2 выполняет операцию XOR для каждого бита чисел n1 и n2. Например, 5 ^ 7 оценивается 2:

1 0 1 (5 in binary)
1 1 1 (7 in binary)
-----
0 1 0 (5 ^ 7 = 2 in binary)

Побитовый оператор XOR имеет 2 интересных свойства:

n ^ n = 0: XOR, выполняемый для того же числа, дает 0

n ^ 0 = n: XOR, выполняемый для числа и ноля, дает то же число

Эти свойства XOR можно использовать для обмена значений между переменными. Давайте посмотрим, как обменять значения a и b:

let a = 1;
let b = 2; a = a ^ b;b = a ^ b;a = a ^ b;
a; // => 2
b; // => 1

Вот объяснение, почему работает обмен:

a = a ^ b

b = a ^ b, на основании 1. a заменяется на a ^ b. Таким образом b = (a ^ b) ^ b = a ^ (b ^ b) = a ^ 0 = a. Помним, что b сейчас равно a.

a = a ^ b, на основании 1. a замещено a ^ b, и на основе 2. b замещено a. Таким образом a = (a ^ b) ^ a = b ^ (a ^ a) = b ^ 0 = b. Переменная a становится b.

Если вы находите это объяснение сложным, можете его пропустить. Свойства побитового оператора XOR ( n ^ n = 0 и n ^ 0 = n), составленные в 3 присваиваниях, позволяют менять a и b.

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

Заключение

JavaScript предлагает множество способов обмена значениями между переменными с использованием дополнительной памяти и без.

Первый способ, который я рекомендую для ежедневного использования, — это замена переменных с помощью деструктурирующего присваивания [a, b] = . Это короткий и выразительный подход.

Второй способ — использовать временную переменную. Это хорошая альтернатива подходу деструктурирования.

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

Точно так же, четвертый подход с использованием побитового оператора XOR не использует дополнительную память. Но, опять же, вы ограничены только целыми числами. Какой ваш предпочтительный способ обмена значений между переменными?

Автор: Dmitri Pavlutin

Источник: https://dmitripavlutin.com

Редакция: Команда webformyself.