Which approach is better for assigning conditionally? - javascript

Below code is just initializing two variables, depending on cloudType passed, which can be assigned by either of approaches. In JavaScript less number of lines of code is recommended so I like the second approach also it removes duplication.
Approach one gives me flexibility to add operations in specific case if required in future where as 2nd approach is saving me good amount of bytes also helping me reduce duplication.
switch (cloudType) {
case "aws":
value = this._resetMessageDefaultValues.aws
resetText = this._messages.current.aws
break;
case "private":
value = this._resetMessageDefaultValues.private;
resetText = this._messages.current.private
break;
case "azure":
value = this._resetMessageDefaultValues.azure;
resetText = this._messages.current.azure
break;
}
Or
value = this._resetMessageDefaultValues[cloudType];
resetText = this._messages.current[cloudType]

By all means, I prefer the second code.
If your cloudType variable has a one-to-one mapping to properties of those two other objects, why not make it clear? This also avoids duplicate code.
To be safe, add these checks to your code:
value = this._resetMessageDefaultValues[cloudType];
resetText = this._messages.current[cloudType]
if (typeof value == "undefined" || typeof resetText == "undefined") {
// throw some error
}
This way you'll know that when a new cloudType is added to your system, you should add relevant properties to those other objects.

Amplifying #Mohammad's answer
The second code is already industry standard of referring to object properties through its keys via brackets foo['bar']. If you want to add extra operations, just put in the switch case block below. Still saving you a few bytes than the first solution you wrote
value = this._resetMessageDefaultValues[cloudType];
resetText = this._messages.current[cloudType];
switch (cloudType) {
case "aws": break;
case "private": break;
case "azure": break;
}
Considering the keys truly matches directly to the cloudType variable, and even if it isn't, I advise matching it.

Related

js - is it possible to have two elements on the switch condition? [duplicate]

I'm trying to convert an if statement into a switch statement using javascript. This is the working if statement:
if(!error1(num, a_id) && !error2(num, b_id) && !error3(num, c_id) && !error4(num, d_id)) {
a.innerHTML = num;
Any tips on how to put this into a switch statement would be great. Thanks
You can make this a switch, but it's unclear why you would want to. On first glance, this isn't the kind of situation (selecting amongst a set of values and doing something different for each of them) that you use switch for.
Here's how, though I don't recommend it:
switch (false) {
case !error1(num, a_id):
case !error2(num, b_id):
case !error3(num, c_id):
case !error4(num, d_id):
// Do nothing
break;
default:
a.innerHTML = num;
break;
}
This works in JavaScript, but not in most other languages that have switch. The reason it works is that the case labels are evaluated when the execution point reaches them, and they're guaranteed to be evaluated in source code order. So you're switching on the value false, which will first be tested (using strict equality, ===) against the return value of !error1(num, a_id), and then if that doesn't match, against !error2(num, a_id), etc.; if none of them matches, then they all evaluated true, and the code in the default block runs.

One liner that returns a value if evaluation is truthy and breaks if evaluation falsy?

Here is a piece of code I have in several places in my code:
req = this.getActiveRequestById(message.trans_id);
if (!req) {
break;
}
How can I rewrite this as a one-liner?
EDIT I want to clarify that I need to store the return value in req for later use.
Remove var assignment and apply the condition directly to the value:
if (!this.getActiveRequestById(message.trans_id)) break;
I would not suggest it but if you need to set a variable in a one liner if condition it should work:
if (!(req = this.getActiveRequestById(message.trans_id))) break;
Notice that it generates confusion between comparison and assignment.
if (!(reg = this.getActiveRequestById(message.trans_id))) break;

Dynamic Switch in Javascript

I want to do a switch with dynamic content in javascript, I will put an example:
switch(terrain) {
case "Plains":
terrain = Plains.create(newPosition);
break;
case "Mountains":
terrain = ImpassableMountain.create(newPosition);
break;
case "Hills":
terrain = Hills.create(newPosition);
break;
case "Forest":
terrain = Forest.create(newPosition);
break;
case "River":
terrain = River.create(newPosition);
break;
default:
};
So if I want to add a new Terrain for example Ocean, I want that will be updated automatically. I am thinking about to put all the terrains in a array
var terrainArray = ["Plains","Mountains","Hills","Forest","River","Ocean",...]
But I don't know how to put that in a switch in the most optimized way because if I try
for(var i=0;i<terrainArray.length;i++){
if(terrain==terrainArray[i]){
Terrain.create(newPosition);
}
}
It wouldn't be optimized because it will go through the entire array.
Also I need to put the class dynamically so if that terrain is Plains I need to put Plains.create instead of other, maybe can I do that with an array of classes?
Use an object literal - that makes it much easier and faster as you don't have to loop the array everytime you lookup something. It's also easier to handle dynamically than a switch
const foo = {
Plains: Plains,
Mountains: ImpassableMountains
}
let x = 'Plains';
foo[x].create(newPosition)
You can simply use .indexOf to check if it's in that array and perform actions accordingly.
terrainArray.indexOf(terrain) >=0 ? Terrain.create(newPosition) : null;
To
it will go through the entire array., To find something in array it will.. always

Is it bad to use a "not declared array"? Does the "not declared" array have a proper name in programming?

I was trying to use a if...else statement with arrays without having to declare the arrays. I got it to work this way:
if(['banana','apple','lemon'].indexOf(somevar) >-1)
{
//code
}
else if(['chicken','dog','elephant'].indexOf(somevar) >-1)
{
//code
}
.
.
.
And it keep going this way until some dozens of if...elses. The code is working fine, no problem noticed. Is it a bad pratice? Is it really an array? Can it cause some performance loss, memory leaks, or reference problems? Does the "not declared" array used in this code, if it is really an array, have a proper name in programming?
It seems pointless in my opinion, since you know exactly what element you want.
As for memory, the array should be deallocated as soon as you move to the next statement, and I would personally consider this bad practice in this instance, since, like I said earlier, it doesn't do anything since you know which will be selected.
If it's a static list that the user is going to select an element from, this is alright but I would probably define the array elsewhere and just reference that when needed, so you don't have to create the exact same array over and over again.
I consider it bad practice since if I wanted to add/remove/change an element in an array, I would rather just change the array when it's declared at the top, or change the data source. By sprinkling it through your code, you allow the possibility of hard to maintain code.
How about
switch(somevar) {
case 'banana': case 'apple': case 'lemon'
//...
break;
case 'chicken': case 'dog': case 'elephant'
//...
break;
}
You're just declaring/using arrays on-the-fly. Nothing really wrong with it, it's just one of many coding styles. e.g.
if (somevar == 'banana') || (somevar == 'apple') || etc...) {
...code...
} else if (somevar == 'chicken') || (somevar == 'dog') || etc...) {
... code
}
or perhaps
switch(somevar) {
case 'banana':// fall-through
case 'apple': // fall-through
case ...
.... code ...
break;
case 'chicken':
case 'dog':
etc...
}
They're all valid. It comes down to what your project's code style guidelines are and how many of these comparisons you need to do.
I see no problem, but I would declare these arrays for readability and maintenance:
var fruits = ['banana','apple','lemon'],
animals = ['chicken','dog','elephant'];
if(fruits.indexOf(somevar) > -1)
{
//code
}
else if(animals.indexOf(somevar) > -1)
{
//code
}
Now it's clearer why you check if someVar is in one array or the other, and it's easier to update the arrays - I want add another animal, I go to the animals array, not "the first else if block".
Yes, ['banana','apple','lemon'] is an array, but your code will fail when somevar === 'chicken' because ['banana','apple','lemon'].indexOf(somevar) === 0, which is a falsey value.
Also, your else if statement is redundant. You should check the indices by doing:
if(['banana','apple','lemon'].indexOf(somevar) >= 0 ) { ... }

Using an array through a switch() statement in Javascript

I'm trying to develop a simplified poker game through Javascript. I've listed all possible card combinations a given player might have in its hand ordered by its value, like this:
switch(sortedHand)
{
//Pair
case [1,1,4,3,2]: sortedHand.push(1,"Pair"); break;
case [1,1,5,3,2]: sortedHand.push(2,"Pair"); break;
case [1,1,5,4,2]: sortedHand.push(3,"Pair"); break;
case [1,1,5,4,3]: sortedHand.push(4,"Pair"); break;
case [1,1,6,3,2]: sortedHand.push(5,"Pair"); break;
case [1,1,6,4,2]: sortedHand.push(6,"Pair"); break;
case [1,1,6,4,3]: sortedHand.push(7,"Pair"); break;
case [1,1,6,5,2]: sortedHand.push(8,"Pair"); break;
case [1,1,6,5,3]: sortedHand.push(9,"Pair"); break;
case [1,1,6,5,4]: sortedHand.push(10,"Pair"); break;
Even though the "sortedHand" array stores values succesfully (as I've seen through console.log), the switch() statement always returns the default case, and everyone gets an straight flush. I fear this is a matter of the literal approach I've used to declare possible array values to be compared with the whole of "sortedHand", but I don't know any better. Is it even possible to use switch() in such a manner?
You can try switching on a textual representation of the array.
switch(sortedHand.join(' '))
{
//Pair
case '1 1 4 3 2': sortedHand.push(1,"Pair"); break;
case '1 1 5 3 2': sortedHand.push(2,"Pair"); break;
case '1 1 5 4 2': sortedHand.push(3,"Pair"); break;
case '1 1 5 4 3': sortedHand.push(4,"Pair"); break;
// etc.
}
As an alternative to specifying every case directly, perhaps build a function dispatch table using an object and get rid of the switch entirely.
var dispatch = {};
// Build the table however you'd like, for your application
for (var i = 0; i < 10; i++) {
(function(i) {
var hand = ...; // Add your hand logic here
dispatch[hand] = function() { sortedHand.push(i, "Pair"); };
})(i);
}
// Execute your routine
dispatch[sortedHand.join(' ')]();
the switch() statement always returns the default case
That's because the comparison doesn't check the array contents, but the array object itself. Objects are considered equal by their identity, so nothing will be equal to an object instantiated by a literal.
Is it even possible to use switch() in such a manner?
Yes, one can use objects in switch statements, but you would have to use references in the cases. Not applicable to your problem.
In your case, I'd suggest a stringification:
switch(sortedHand.join())
{
//Pair
case "1,1,4,3,2": sortedHand.push(1,"Pair"); break;
case "1,1,5,3,2": sortedHand.push(2,"Pair"); break;
case "1,1,5,4,2": sortedHand.push(3,"Pair"); break;
case "1,1,5,4,3": sortedHand.push(4,"Pair"); break;
case "1,1,6,3,2": sortedHand.push(5,"Pair"); break;
case "1,1,6,4,2": sortedHand.push(6,"Pair"); break;
case "1,1,6,4,3": sortedHand.push(7,"Pair"); break;
case "1,1,6,5,2": sortedHand.push(8,"Pair"); break;
case "1,1,6,5,3": sortedHand.push(9,"Pair"); break;
case "1,1,6,5,4": sortedHand.push(10,"Pair"); break;
but I guess there's an even better, arithmetic solution to detect the patterns you're after. That would be shorter and faster, but I'm not sure what exactly this snippet is supposed to do.
a faster, potentially reusable, and more flexible way of doing it is to use an object instead of case:
var ok= {
'1 1 4 3 2':1,
'1 1 5 3 2':2,
'1 1 5 4 2':3,
'1 1 5 4 3':4
}[ sortedHand.join(' ') ] ;
if(ok){ sortedHand.push( ok ,"Pair"); }
objects work great when one output is hinged on one input. if you need to do five things in each case, then you have to use case, but if you just need X to turn into Y, (a 1:1), Look Up Tables in the shape of Objects are ideal.
i imagine a RegExp can work here, i used them on a connect4 game to identify 4 in a row, but the above logic table should work as well or better than what you describe.
That will not quite work as you have it, but you can use sortedHand.join(',') and compare it with [1,1,1,2,5].join(',') which will compare the two arrays and should be true if their contents were the exact same (Be careful with numbers typed as strings!)
To be fair, though, I can't imagine why you would design your logic like that. Even a simple card game has hundreds of thousands of possible hands. You might do better using underscore.js's collection managing functions as it will be simpler, and just a better practice.
There are 1274 possible combinations of 5 cards in a regular deck. Listing them all out in a switch statement is completely ridiculous. Why not just have a function count any duplicates to check for 2,3,4-of-a-kinds and then check for straights? (Your array doesn't show suit so I'm assuming you are leaving it out).
But if you really want to do it that way, you could use a string. Strings work with switches, and you can even use them like arrays. e.g. "123"[0] == '1'. You can change them back and forth user functions like parseInt.
Since no one suggested this, use a for loop and count the number of cards with exactly the given value. Having such a function you can call 'cardCount = count(sortedHand, cardNumber)'. And of cause looping through all possible card-numbers will give you the hands.
Since a given player can only have 1x2, 2x2, 1x3, 1x3+1x2, 1x4 or straights/streets, you can return an array of all hits being arrays/objects stating the count and the cardNumber involved. So [{2, 5}, {3, 6}] for a full house.

Categories

Resources