Why can't I swap 2 variables in JavaScript? - javascript

I am trying to swap two variables in JavaScript, but my code does not work. Can anyone tell me why?
This should return 10, 5 I think, because I already called the swap function. But instead, it returns 5, 10.
function swap(a, b) {
var temp = a;
a = b;
b = temp
}
var x = 5;
var y = 10;
swap(x, y);
console.log(x, y);

JavaScript, like Java, is pass by reference only. This means that while your function does swap the values, the actual values of x and y in the calling scope have not been swapped. One workaround here might be to return an array of values, swapped:
function swap(a, b) {
return [b, a];
}
var x = 5;
var y = 10;
[x, y] = swap(x, y);
console.log("x after swap = " + x);
console.log("y after swap = " + y);
Note that here the critical line is the assignment:
[x, y] = swap(x, y);
This reassigns x and y to the swapped array in one line.

You can use Destructuring assignment method:
let a = 1;
let b = 2;
[a, b] = [b, a];
a; // => 2
b; // => 1

Javascript function values aren't passed by reference, instead values get copied in a,b. So instead return values:
function swap(a, b) {
return [b, a];
}
Later get it:
[x, y] = swap(x, y);

You can achieve this using JavaScript's objects, which passed by sharing, similar to pass by reference you may have experienced in other languages. This allows you to do a few things that are not possible with primtive values -
function ref (value) {
return { value }
}
function deref (t) {
return t.value
}
function set (t, value) {
t.value = value
}
function swap (a, b) {
const temp = deref(a)
set(a, deref(b))
set(b, temp)
}
const x = ref(3)
const y = ref(5)
swap(x,y)
console.log(deref(x), deref(y)) // 5 3
You can make this abstraction in any way you choose -
const box = v => [v]
const unbox = t => t[0]
const set = (t, v) => t[0] = v
function swap (a, b) {
const temp = unbox(a)
set(a, unbox(b))
set(b, temp)
}
const x = box(3)
const y = box(5)
swap(x,y)
console.log(unbox(x), unbox(y)) // 5 3

Related

How to return the name of the variable with maximum value from an array using Javascript

I have been trying to return a instead of 100 in Javascript?
However, I believe I am doing something wrong with my loop.
let a = 100
let b = 25
let c = 75
let d = 50
let A = [a,b,c,d]
function solution(A) {
// write your code in JavaScript (Node.js 8.9.4)
let result = []
let max = Math.max(...A)
for (let i = 0; i < A.length; i++)
if (A[i] === max){
return A[i]
}
return A
}
console.log( solution(A))
As #user1599011 mentioned, this is not possible using an array as your example.
I'd recommend using an object, with the key's as desired, and the value as the integer. We can use the the shorthand object syntax to create the object like so:
let A = { a, b, c, d };
Then you can use reduce() on Object.keys() to search for the key with the heights value:
let a = 100
let b = 25
let c = 75
let d = 50
let A = { a, b, c, d };
function solution(A) {
return Object.keys(A).reduce((prev, cur) => A[prev] > A[cur] ? prev : cur);
}
console.log(solution(A)); // a
As has been pointed out, use an object. Pass that object to solution(); one way you can find and return the key of the highest value is to use Object.entries() to produce an array with [key, value], e.g., [a,100], as elements, sort by value in descending order then return the key of element in index 0.
let a = 100;
let b = 25;
let c = 75;
let d = 50;
let A = {a,b,c,d};
function solution(A) {
return Object.entries(A).sort((a, b) => b[1] - a[1])[0][0]
}
console.log( solution(A) )
Note: If there are multiple keys with the highest value, this will return only one key.

Is there any way to sum all sub array item and then multiply all sub arrays using a 'for' or 'for-of' loop?

i want to create a function using for() or for of() loop, which take an nested array as argument then add and multiply its item.
Suppose, myArray = [[5,6],[9,2],[4,8]]
Now i want to process it like: [[5+6] * [9+2] * [4+8]]
I solve it using .map() and .reduce(), but is there any way to do same using classic for() or for of() loop. this is my trial.
let myArray = [[1,2],[3,4],[5,6]]
function multyPlus(array) {
resul = 0
for (const subArray of array) {
for (const num of subArray) {
resul += num
}
resul *= subArray
}
return resul
}
console.log(multyPlus(myArray));
//Nan
I would try a two step system that first adds the numbers, then multiplies it to the previous numbers:
function sum(array) {
var total = 0;
for (var item of array)
total += item;
return total;
}
var myArray = [[5,6],[9,2],[4,8]];
var output = 1;
for (var item of myArray)
output *= sum(item);
Maybe Like This:
let myArray = [[1,2],[3,4],[5,6]]
function multyPlus(_array){
var out = 1;
for(var key1 in _array){
var out2 = 0;
for(var key2 in _array[key1]){
out2 += _array[key1][key2];
}
out = out * out2;
}
return out;
}
console.log(multyPlus(myArray));
You can define separate adder and multiplier functions -
const adder = (nums = []) =>
{ let r = 0
for (const n of nums)
r += n
return r
}
const multiplier = (nums = []) =>
{ let r = 1
for (const n of nums)
r *= n
return r
}
const myCalc = (input = []) =>
{ const r = []
for (const x of input)
r.push(adder(x))
return multiplier(r)
}
const result =
myCalc([[1,2],[3,4],[5,6]])
console.log(result) // 231
That said, I think the functional approach is superior when you use named functions. Each function is highly reusable and there's virtually no room for bugs to hide -
const add = (x = 0, y = 0) =>
x + y
const mult = (x = 0, y = 0) =>
x * y
const sum = (nums = []) =>
nums.reduce(add, 0)
const product = (nums = []) =>
nums.reduce(mult, 1)
const myCalc = (input = []) =>
product(input.map(sum)) // <-- easy peasy!
const result =
myCalc([[1,2],[3,4],[5,6]])
console.log(result) // 231
If you have something against map and reduce, you can write myCalc and sum by hand using simple recursion -
const sum = ([ x, ...more ]) =>
x === undefined
? 0
: x + sum(more)
const myCalc = ([ x, ...more ]) =>
x === undefined
? 1
: sum(x) * myCalc(more)
const result =
myCalc([[1,2],[3,4],[5,6]])
console.log(result) // 231

Swapping terms using Assignment de-structuring wont work inside a function

let a = 'alpha', b = 'beta';
[a,b] = [b,a];
This swaps the values of a and b as intended;
but when placed inside a function it doesn't work
let c = 'charlie', d = 'delta';
swapVar = (x,y) => [x,y] = [y,x]
swapVar(c,d);
What am I missing here?
When you do
let a = 'alpha', b = 'beta';
[a,b] = [b,a];
You're swapping the values of a and b.
When you do
let c = 'charlie', d = 'delta';
swapVar = (x,y) => {
// x and y are separate variables scoped within this block
[x,y] = [y,x]
console.log(x,y); // it is swapped alright but isn't reflected on c and d
c = x;
d = y;
// Now the value will have been reflected.
}
swapVar(c,d);
So, within the function the values are swapped but aren't reflected outside. You could modify the program like this:
swapVar = (x,y) => [y,x]
[c, d] = swapVar(c, d); // now you're reflecting the swapped values on the outside
To have the intended effect.
You are doing the swap in a scope where the variables aren't being "exported".
In the first example, you act on the actual variables a and b in the scope they are defined in.
However, in the second example, you are acting on the variables x and y which are the same value as c and d but aren't the actual c and d since they are primitives so the c and d outside the scope of the arrow function is not affected.
{
let a = 'alpha',
b = 'beta';
console.log("Test 1");
console.log(`before a: ${a} b: ${b}`);
[a, b] = [b, a];
console.log(`after a: ${a} b: ${b}`);
}
{
let c = 'charlie',
d = 'delta';
console.log("Test 2");
console.log(`before c: ${c} d: ${d}`);
swapVar = (x, y) => [x, y] = [y, x]
/*
function swapVarExpanded(x, y) {
const tmp = [y, x];
x = tmp[0];
y = tmp[1];
// Doesn't actually matter
// because x and y die at the next closing curly brace due to scope
}
*/
swapVar(c, d);
console.log(`after c: ${c} d: ${d}`);
}

how to sort an array based on the contents of another array

I have an array X = [12,14,12,45,12] and another array Y = [34,12,23,47,20]. I am sorting the X array, so now X = [12,12,12,14,45]. Now I want to sort Y as Y = [34,23,20,12,47]. Any help would be appreciated. Thanks
You can build an array of indexes and sort it using a custom comparator function that references X and, then, use that array to "sort" Y:
var X = [12,14,12,45,12];
var Y = [34,12,23,47,20];
var xIndexes = [];
X.forEach((value, index) => xIndexes.push(index));
xIndexes.sort((a, b) => X[a] < X[b] ? -1 : X[a] > X[b] ? 1 : 0);
var newX = [];
var newY = [];
xIndexes.forEach((index) => {
newX.push(X[index]);
newY.push(Y[index]);
});
console.log(newX);
console.log(newY);
You can combine the arrays into a single array. Sort by the original values of X, and then separate back into 2 arrays.
const X = [12,14,12,45,12];
const Y = [34,12,23,47,20];
const [Xsorted, Ysorted] =
X.map((x, i) => [x, Y[i]])
.sort((a, b) => a[0] - b[0])
.reduce((arrs, [x, y]) => {
const [X, Y] = arrs;
X.push(x);
Y.push(y);
return arrs;
}, [[], []]);
console.log(Xsorted);
console.log(Ysorted);

Performing Set calculations in javascript array

I have 2 arrays lets say:
A = [1,2,3,4,5] and B = [1,2,3,6,7]
and I'd like to perform the following 'set calculations':
C = (A ∩ B)
D = A - (A ∩ B)
E = B - (A ∩ B)
Essentially:
C = [1,2,3]
D = [4,5]
E = [6,7]
Is there a smart way to do this or am I going to have to cross check each array member with loops and ifs? I cannot use an external library (like math.js or w/e).
Thanks in advance.
filter() can at least hide the loops for you:
A = [1,2,3,4,5];
B = [1,2,3,6,7];
C = intersection(A, B);
D = arrayDiff(A, C);
E = arrayDiff(B, C);
console.log(JSON.stringify(C));
console.log(JSON.stringify(D));
console.log(JSON.stringify(E));
function intersection(a, b) {
return a.filter(
function(el) {
return b.indexOf(el) >= 0;
}
);
}
function arrayDiff(a, b) {
return a.filter(
function(el) {
return b.indexOf(el) < 0;
}
);
}
As of ES6, Javascript has an inbuilt set object, which offers neat ways to do the above operations.
var intersection = function(setA, setB){
return new Set([x for (x of setA) if (setB.has(x))]);
}
var difference = function(setA, setB){
return new Set([x for (x of setA) if (!setB.has(x))]);
}
A = new Set([1,2,3,4,5]);
B = new Set([1,2,3,6,7]);
// A ∩ B = ([1,2,3])
intersection(A, B);
// A \ B = ([4,5])
difference(A, B);
// B \ A = ([6,7])
difference(B, A);

Categories