How to simplify an if/else statement with assignments on it - javascript

I was wondering if there is any way to simplify this if/else statement, just curious about finding an inline way of solving this (variables are this trivial due to experimenting purposes:
var a = false;
var b = false;
var condition = true;
if (condition) {
a = true;
} else {
b = true;
}
I took it as a code challenge with a colleague, join us if feeling like that, cheers :)

What about
var a =condition;
var b = !a;

You can use destructuring to assign true / false according to condition:
const condition = true;
const [a, b] = condition ? [true, false] : [false, true]
console.log({ a, b });
And you can optimize it to:
const condition = true;
const [a, b] = [condition, !condition]
console.log({ a, b });
And using default values, you can shorten it a bit more, although it's a slight abuse of the default values:
const condition = true;
const [a, b = !a] = [condition]
console.log({ a, b });

Related

How to refactor if blocks with repeated conditions?

Let's say I have some 6 conditions (a-f) and if statements listed below. As you can see there is a pattern for these if statements. Every next if statement has almost the same conditions as the previous one but the first condition which was used previously is removed.
if(a && b && c && d && e && f)
return 5;
if(b && c && d && e && f)
return 4;
if(c && d && e && f)
return 3;
if(d && e && f)
return 2;
if(e && f)
return 1;
if (f)
return 0;
return -1;
I think there is no need to have so many elaborate conditions, especially as there are cases which introduce some redundant condition checks and I would prefer to avoid that. I've tried to rewrite it, but I've only come up with something like this:
let res = -1;
if(f) {
res = 0;
if(e) {
res = 1;
if(d) {
res = 2;
if(c) {
res = 3;
} if(b) {
res = 4;
if(a) {
res = 5;
}
}
}
}
}
return res;
This way I no longer have redundant condition checks, but this solution still looks overcomplicated. Are there some clever ways to rewrite it so that I can have a simple solution without redundant checks?
Your nested if statements aren't that bad - they get rid of the duplication quite efficiently, and create a linear structure! You can further shorten the code by using a loop:
let res = -1;
for (const flag of [f, e, d, c, b, a]) {
if (flag) res++;
else break;
}
return res;
This still evaluates all the conditions up-front, so if they are costly to compute you might want to use functions that you can evaluate when needed:
let res = -1;
for (const getFlag of [()=>f, ()=>e, ()=>d, ()=>c, ()=>b, ()=>a]) {
if (getFlag()) res++;
else break;
}
return res;
If the conditions are cheap, and you also know that if one is false all the remaining ones are false as well, you don't even need to break the loop. It can then be simplified into a single expression:
return -1 + f + e + d + c + b + a;
Put the conditions into an array, along with the results.
const conds = [[a, 5], [b, 4], [c, 3], [d, 2], [e, 1], [f, 0]];
while (conds.length) {
if (conds.every(([cond]) => cond)) {
return conds[1];
}
conds.shift();
}
return -1;

Find the newly added elements of an Array of Objects with Lodash

Imagine we have two Arrays.
var a = [B, C, E];
var b = [A, B, C, D, E];
Array a is our default Array that we have saved locally.
Now the api we fetch from sends us the new version of this Array a called b.
How can I use lodash so I can get the difference of this two arrays so I get in this case
[A, D] returned ?
UPDATE:
I came up with my own solution it kinda worked, so only try this if the accepted answer does not work for some reason:
const getObjectDiff = (newArr, oldArr) => {
if (_.isEqual(newArr, oldArr)) {
return true;
} else {
const checkLength = newArr.length;
const checkerLength = oldArr.length;
var indexes = [];
var falseIndexes = [];
var allIndexes = [];
for (let i = 0; i <= checkerLength; i++) {
for (let j = 0; j <= checkLength - 1; j++) {
allIndexes.push(i);
if (_.isEqual(newArr[i], oldArr[j])) {
indexes.push(i);
} else {
falseIndexes.push(i);
}
}
}
const falseUniqueIndexes = _.uniq(falseIndexes);
return _.difference(falseUniqueIndexes, indexes);
}
};
```
We can use _.differenceWith along with the _.isEqual to check deep equality between objects.
_.isEqual will perform a deep comparison between two objects to see if they are equivalent so we can use this to compare, say, objects that have been decoded from JSON.
This is a simple example, however, this will work with much more complex objects as long as they are equal (as determined by lodash)
const apiResponseA = '[{"id":"B"},{"id":"C"},{"id":"E"}]';
const apiResponseB = '[{"id":"A"},{"id":"B"},{"id":"C"},{"id":"D"},{"id":"E"}]'
const a = JSON.parse(apiResponseA);
const b = JSON.parse(apiResponseB);
console.log("a:", apiResponseA)
console.log("b:", apiResponseB)
console.log("Difference:", JSON.stringify(_.differenceWith(b,a, _.isEqual)));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" integrity="sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==" crossorigin="anonymous"></script>
I realize you asked specifically for a lodash solution, but I just want to mention that you could do this pretty simply without a 3rd party library - just use Array.prototype.filter and Array.prototype.includes, like this:
var a = ['B', 'C', 'E'];
var b = ['A', 'B', 'C', 'D', 'E'];
function getDifference(a, b) {
return b.filter(letter => !a.includes(letter));
}
console.log(getDifference(a, b));

Javascript if else loop?

I'm sure there probably is, however I'm not sure what it's called so apologises if this is something super similar. I'm wondering if there's a faster way to code the following:
var b = "#ff0002";
var o = "#46c029";
var i = "#f2ec00";
var n = "#f64c98";
var g = "#52c6f3";
if(a==1){
return b;
}else if(a==2){
return o;
}else if(a==3){
return i;
}else if(a==4){
return n;
}else if(a==5){
return g;
}
Yeah, lookup array:
return [b, o, i, n, g][a - 1];
Not necessarily faster, but definetly shorter :)
If you have large number of strings to compare from use Object like this:
myObj = {1: '#ff0002', 2: '#46c029', 3: "#f2ec00", 4: "#f64c98", 5: "#52c6f3"}
console.log(myObj[3]);
If you are using ES6 you can use Map() like this:
const myMap = new Map([[1, '#ff0002'], [2, '#46c029'], [3, "#f2ec00"], [4, "#f64c98"], [5, "#52c6f3"]])
console.log(myMap.get(3)); // or any key

Swapping object variables in Javascript without using a 3rd variable

There is a well known method to swap 2 numeric variables without using a 3rd variable with simple arithmetic operations.
a = 3;
b = 5;
b += a;
a = b - a;
b -= a;
console.log(a); //5
console.log(b); //3
No mystery here. But I need to swap two variables that are objects and I have no idea how to tackle this.
The objects are very complex with properties of different data types and methods. Here is an example for simplification:
a = {
label: "xxxxxxx",
active: false,
doThatThang: function(val) {
//some code
}
};
I'm currently using a 3rd variable to perform the swap but the objects are really big and it's messing with the animation where the variables are swapping values.
Use ES6 array destructuring.
let a = 1;
let b = 2;
[a, b] = [b, a];
console.log(a);
console.log(b);
Ref: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
Try ES6 Array Destructing assignment.
DEMO
let a = {
label: "111111",
active: false,
doThatThang: function(val) {
//some code
}
};
let b = {
label: "222222",
active: false,
doThatThang: function(val) {
//some code
}
};
console.log("Before swap");
console.log(a);
console.log(b);
[a, b] = [b, a];
console.log("After swap");
console.log(a);
console.log(b);
var a=1,
b=2,
output=document.getElementById('output');
output.innerHTML="<p>Original: "+a+", "+b+"</p>";
b = [a, a = b][0];
output.innerHTML+="<p>Swapped: "+a+", "+b+"</p>";
<div id="output"></div>
Use a third variable when swapping objects. There is no simpler way to do it in ES5.
var first = {property: 'value'}
var second = {more: 'stuff'}
console.log('Before')
console.log(first)
console.log(second)
var temp = first
first = second
second = temp
console.log('After')
console.log(first)
console.log(second)
Let Say a = 3 and b=5.
Then
a = a+b (ie 8)
b= a-b (ie 8-5 = 3)
a= a-b (ie 8-3 = 5).
Now these are swapped without using 3rd variable.

How to swap two variables in JavaScript

I have this two variables:
var a = 1,
b = 2;
My question is how to swap them? Only this variables, not any objects.
Here's a one-liner to swap the values of two variables.
Given variables a and b:
b = [a, a = b][0];
Demonstration below:
var a=1,
b=2,
output=document.getElementById('output');
output.innerHTML="<p>Original: "+a+", "+b+"</p>";
// swap values for variables "a" and "b"
b = [a, a = b][0];
output.innerHTML+="<p>Swapped: "+a+", "+b+"</p>";
<div id="output"></div>
ES6 (Firefox and Chrome already support it (Destructuring Assignment
Array Matching)):
let a = 5, b = 6;
[a, b] = [b, a];
console.log(`${a} ${b}`);
You can do this:
var a = 1,
b = 2,
tmp;
tmp = a;
a = b;
b = tmp;
For readability and maintainability, this can't be beat (at least in JavaScript). Anybody maintaining the code (including you six months from now) will know exactly what's going on.
Since these are integers, you can also use any number of clever tricks1 to swap without using a third variable. For instance you can use the bitwise xor operator:
let a = 1, b = 2;
a = a ^ b;
b = a ^ b;
a = a ^ b;
console.log('a is now:', a);
console.log('b is now:', b);
This is called the XOR swap algorithm. Its theory of operation is described in this Wikipedia article.
1"The competent programmer is fully aware of the limited size of his own skull. He therefore approaches his task with full humility, and avoids clever tricks like the plague." — Edsger W. Dijkstra
Don't use the code below. It is not the recommended way to swap the values of two variables (simply use a temporary variable for that). It just shows a JavaScript trick.
This solution uses no temporary variables, no arrays, only one addition, and it's fast.
In fact, it is sometimes faster than a temporary variable on several platforms.
It works for all numbers, never overflows, and handles edge-cases such as Infinity and NaN.
a = b + (b=a, 0)
It works in two steps:
(b=a, 0) sets b to the old value of a and yields 0
a = b + 0 sets a to the old value of b
Since ES6, you can also swap variables more elegantly:
var a = 1,
b = 2;
[a, b] = [b, a];
console.log('a:', a, 'b:', b); // a: 2 b: 1
You can now finally do:
let a = 5;
let b = 10;
[a, b] = [b, a]; // ES6
console.log(a, b);
Here's a one-liner, assuming a and b exist already and have values needing to be swapped:
var c=a, a=b, b=c;
As #Kay mentioned, this actually performs better than the array way (almost 2x as fast).
You could use a temporary swap variable or XOR.
a = a ^ b
b = a ^ b
a = a ^ b
This is just a basic logical concept and works in every language that supports XOR operation.
edit: see the Comments. Forgot to tell that this works for sure only with integer. Assumed the integer variables from question's thread
Use a third variable like this:
var a = 1,
b = 2,
c = a;
a = b; // must be first or a and b end up being both 1
b = c;
DEMO - Using a third variable
As your question was precious "Only this variables, not any objects. ", the answer will be also precious:
var a = 1,
b = 2
a=a+b;
b=a-b;
a=a-b;
it's a trick
And as Rodrigo Assis said, it "can be shorter "
b=a+(a=b)-b;
Demo:
http://jsfiddle.net/abdennour/2jJQ2/
ES6 Destructuring:
Using an array: [a, b] = [b, a]; // my favorite
Using an object: {a, b} = {a:b, b:a}; // not bad neither
How could we miss these classic oneliners
var a = 1, b = 2
a = ({a:b, _:(b=a)}).a;
And
var a = 1, b = 2
a = (_=b,b=a,_);
The last one exposes global variable '_' but that should not matter as typical javascript convention is to use it as 'dont care' variable.
I see kind of programming olympiad here. One more tricky one-line solution:
b = (function(){ a=b; return arguments[0]; })(a);
Fiddle: http://jsfiddle.net/cherniv/4q226/
Single line swapping
a = a^b^(b^=(a^b));
var a = 5;
var b = 10;
b = [a, a = b][0];
//or
b = [a, a = b];
b = b[0];
//or
b = [a, b];
a = b[1];
b = b[0];
alert("a=" + a + ',' + "b=" + b);
remove or comment the 2 //or's and run with the one set of code
http://jsfiddle.net/USdv8/57/
We are able to swap var like this :
var val1 = 117,
val2 = 327;
val2 = val1-val2;
console.log(val2);
val1 = val1-val2;
console.log(val1);
val2 = val1+val2;
console.log(val2);
first way,
var a = 5, b = 9;
a = a - b;
b = a + b;
a = b - a;
console.log(a, b);
second way
var a = 19, b = 22;
[a, b] = [b, a];
console.log(a, b);
simple and clear answer.
Because I hear this method runs slower:
b = [a, a = b][0];
If you plan on storing your vars in an object (or array), this function should work:
function swapVars(obj, var1, var2){
let temp = obj[var1];
obj[var1] = obj[var2];
obj[var2] = temp;
}
Usage:
let test = {a: 'test 1', b: 'test 2'};
console.log(test); //output: {a: 'test 1', b: 'test 2'}
swapVars(test, 'a', 'b');
console.log(test); //output: {a: 'test 2', b: 'test 1'}
We can use the IIFE to swap two value without extra parameter
var a = 5, b =8;
b = (function(a){
return a
}(a, a=b));
document.write("a: " + a+ " b: "+ b);
Till ES5, to swap two numbers, you have to create a temp variable and then swap it.
But in ES6, its very easy to swap two numbers using array destructuring. See example.
let x,y;
[x,y]=[2,3];
console.log(x,y); // return 2,3
[x,y]=[y,x];
console.log(x,y); // return 3,2
Know more about JavaScript ES6 destructuring
Although the same answer is given previously, but here is a png to describe it.
Simplest form possible:
let a = 2, b = 4;
[b, a] = [a, b];
a more verbose approach would be
let a = 2, b = 4;
a = [a, b];
b = a[0];
a = a[1];

Categories