I'm creating through a PHP loop (the reason of the loop is because I want more or less cases) a switch Javascript function, that outputs this:
function my_function(array_name) {
switch (true) {
case (array_name[1] < x < array_name[2]):
console.log("between: 1 & 2");
break;
case (array_name[2] < x < array_name[3]):
console.log("between: 2 & 3");
break;
default:
console.log("none");
break;
}
}
Now when the document is loaded I create a Javascript array which contains the values I want to pass to the function.
var array_to_execute = [0,1000,2000,3000];
How can I call the function after this array is created passing these values? Something like:
my_function(array_to_execute);
That would result in executing:
switch (true) {
case (1000 < x < 2000):
console.log("between: 1 & 2");
break;
case (2000 < x < 3000):
console.log("between: 2 & 3");
break;
default:
console.log("none");
break;
}
The function call that you've got in mind (my_function(array_to_execute)) should be just fine!
The problems you're probably having are because:
case (array_name[1] < x < array_name[2]):
does not work the way you think it does. (It ends up comparing a truth value to a number.) Use this instead and you should be good to go:
case (array_name[1] < x && x < array_name[2]):
Related
I've created a question and answer page to determine the level of interest of each user for different products
like this:
how much u like x (betwin 1-10)
These questions are more than 30, and if I want to write a single command line for each possibilities, it's almost impossible.
the commands do like this:
if $a <=5 and $b <=6 and $c <=7 and... do ...
if $a<= 8 and $b <=7 and $c >= 5 and $d <=8 do...
I want the commands to work this way
Is there a better way to do this?
thanks
For this you could use a switch statement. Documentation: http://php.net/manual/en/control-structures.switch.php
Example code:
$i = 10;
switch($i):
case ($i <= 0): // or for example: case (0)
return 'It\'s 0 or lower than 0';
break;
case ($i > 0 && $i < 10):
return 'Number is between 0 and 10';
break;
case ($i >= 10):
return 'Number is 10 or higher';
break;
default:
return false;
endswitch;
// You can use echo instead of return, but i prefer to use these statements in a function instead of the html page.
More information about the differences between if and switch is provided by Masivuye Cokile as a comment in your question: Which is Faster and better, Switch Case or if else if?
I hope this helped. Let me know.
I am building a percentage bar for my website based on pre-defined numbers (not server load percentage). When I use my switch statements to determine the color (based on "percentage range") it has the correct percentage, but the wrong color.
My php
$max = 250000;
$heat = 200000; //$_SESSION['warrents'];
$percent[0] = ($heat / $max) * 100;
if ($percent[0] > 100) { $percent[0] = 100; }
switch ($percent[1]) {
case ($percent[0] < 25):
$percent[1] = "green";
break;
case ($percent[0] >= 25 && $percent[0] <50):
$percent[1] = "yellow";
break;
case ($percent[0] >= 50 && $percent[0] <75):
$percent[1] = "orange";
break;
case ($percent[0] >= 75):
$percent[1] = "red";
break;
}
echo $percent[0]." ".$percent[1];
The echo says 80 green
80 is correct; however, it should be red, not green. Any ideas what I'm doing wrong here?
Thanks!
Of course as soon as I posted this I figured out my problem:
switch ($percent[1]) {
should be
switch ($percent[0]) {
Thanks for those who looked!
I needed a percentage bar on the site I am working on at the moment; It is currently on my development domain, so you can check it out and see yourself (Yours can look however you want).
The following code will take a percentage value and return a color value from red-amber-green:
function getColorFromPercent(percent) {
colors = [
'FF0000',
'FF1000',
'FF2000',
'FF3000',
'FF4000',
'FF5000',
'FF6000',
'FF7000',
'FF8000',
'FF9000',
'FFA000',
'FFB000',
'FFC000',
'FFD000',
'FFE000',
'FFF000',
'FFFF00',
'F0FF00',
'E0FF00',
'D0FF00',
'C0FF00',
'B0FF00',
'A0FF00',
'90FF00',
'80FF00',
'70FF00',
'60FF00',
'50FF00',
'40FF00',
'30FF00',
'20FF00',
'10FF00'
];
return '#' + colors.reverse()[Math.floor(parseFloat(percent) / (100 / colors.length))];
}
document.getElementById('test').style.backgroundColor = getColorFromPercent('23.8%');
<div id="test">23.8%</div>
Good Luck, and If you have any issues - Let me know!
Information
I am currently making a user level system for my website. I have a points column in my users table that will get incremented on certain awards and milestones etc.
Problem
I have this switch statement that takes the users points and converts them into a level that gets returned. But it is saying that "0" isn't in 0-100 option, and rather in the 100-200 option.
function userLevel($points){
switch ($points) {
case ($points>=0 && $points<100):
return 1; // Level 1
break;
case ($points>=100 && $points <200):
return 2; // Level 2
break;
case ($points>=200 && $points<300):
return 3; // Level 3
break;
case ($points>=300 && $points<400):
return 4; // Level 4
break;
}
}
echo userLevel(0);
I feel like this is one of those "You have been coding too much for one sitting" questions and the answer is right in front of me, but I just can't see it!
Since your using conditions for your cases, you probably want to switch on TRUE:
function userLevel($points){
switch (true) {
case ($points>=0 && $points<100):
return 1; // Level 1
break;
case ($points>=100 && $points <200):
return 2; // Level 2
break;
case ($points>=200 && $points<300):
return 3; // Level 3
break;
case ($points>=300 && $points<400):
return 4; // Level 4
break;
}
}
The reason is your code is becoming this
function userLevel($points){
switch (0) {
case (true): // compare 0 to true
return 1; // Level 1
break;
case (false): // compare 0 to false
return 2; // Level 2
break;
case (false):
return 3; // Level 3
break;
case (false):
return 4; // Level 4
break;
}
}
echo userLevel(0);
The first case does not match because 0 != true
the second case does match because 0 == false
Therefore the second option runs
as others have said use true in the switch so then it becomes true == true as the first case, making that run
One other thing you can do to eliminate a lot of code for this is to simply do this
return floor(($points+100)/100);
NOTE: I am aware that this is not acceptable code, I am seeking to understand what the interpreter is doing, not advice on how else to achieve the same result!
I've since read up enough to realize that I can't and shouldn't be attempting to use |,|| or XOR in defining a switch caseāso please don't comment to the effect of "don't do that", I'm just trying to understand what the interpreter is doing with such statements and to understand the strangeness of the behavior. I'm using PHP 5.3.1.
This is what I was actually intending to do and am now using, please don't recommend code:
for ($i=0; $i<count($this->header); $i++) {
switch($i) {
case 0:
$this->header[ $i ] = $this->header[ $i ] ? $this->header[ $i ] : -5; //angle from goal
break;
case 1:
$this->header[$i] = $this->header[$i] ? $this->header[$i] : -5; //miss penalty
break;
case 2:
$this->header[$i] = $this->header[$i] ? $this->header[$i] : -10; //miss penalty
break;
case 3:
$this->header[ $i ] = $this->header[ $i ] ? $this->header[ $i ] : -10; //error penalty
break;
}
}
But got curious if I could do:
for ($i=0; $i<count($this->header); $i++) {
switch($i) {
case 0 || 1:
$this->header[ $i ] = $this->header[ $i ] ? $this->header[ $i ] : 15; //angle from goal
break;
case 2 || 3:
$this->header[$i] = $this->header[$i] ? $this->header[$i] : -5; //miss penalty
break;
}
}
and, perversely, this does run, but very slowly (like, seconds), and though of course it evaluates (0||1) not at all the way I'd intended (and indeed today was a lesson on the difference between bitwise and logical operators).
But more curious to me was the fact that I could do this, if very slowly and not with the results I'd wanted:
for ($i=0; $i<count($this->header); $i++) {
switch($i) {
case 0 XOR 1:
$this->header[ $i ] = $this->header[ $i ] ? $this->header[ $i ] : 15; //angle from goal
break;
case 2:
$this->header[$i] = $this->header[$i] ? $this->header[$i] : -5; //miss penalty
break;
case 3:
$this->header[$i] = $this->header[$i] ? $this->header[$i] : -5; //miss penalty
break;
}
}
But I could not do this:
for ($i=0; $i<count($this->header); $i++) {
switch($i) {
case 0 XOR 1:
$this->header[ $i ] = $this->header[ $i ] ? $this->header[ $i ] : 15; //angle from goal
break;
case 2 XOR 3:
$this->header[$i] = $this->header[$i] ? $this->header[$i] : -5; //miss penalty
break;
}
}
This was the only one of these terrible, terrible ideas that PHP wouldn't even evaluate.
My question is: why does evaluating these statements take so, so much longer, and why does the last example not run? I considered that PHP was interpreting 0 XOR 1 and comparing true and false, but I couldn't substitute those in and have it still evaluate. Anyone know what's happening here? Thanks!
UPDATE:
Comments requested a var_dump($this->header) (in case it isn't obvious, I truncated my initial switch statement from 7 cases to 4 just to avoid spamming lines of identical code, but, given that the var_dump() was requested, I chose to post the whole thing in case it revealed something I couldn't forsee!). Also, yes, it turns out I'd been using an associative array due to forgetting to have called array_values() before setting $this->header, in the second answer below, having made this error turns out to explain the duration of the switch statement, whilst the first answer and second answer together are great walkthroughs of the logic.
array(12) {
["theZone"]=>
NULL
["leftMiss"]=>
NULL
["rightMiss"]=>
NULL
["leftError"]=>
NULL
["rightError"]=>
NULL
["leftHit"]=>
NULL
["rightHit"]=>
NULL
["accuracy"]=>
string(5) "false"
["rt"]=>
string(4) "true"
["disease"]=>
string(3) "yes"
["bars"]=>
string(3) "yes"
["endMessage"]=>
NULL
}
case values have to be SINGLE values. You can't do 2 || 3, because that'll evaluate as
case (2 or 3) -> case TRUE
Similarly, if you were using && (and), you'd get
case (0 and 1) -> case FALSE
You can use 'fallthrough' behavior for the OR logic:
case 2:
case 3:
...code here ...
break;
XOR, you can't do. not with a simple case statement.
comment followup:
for ($i = 0; $i < 5; $i++) {
switch($i) {
case 0 xor 1: echo "0 xor 1: $i\n"; break;
case 2 xor 3: echo "2 xor 3: $i\n"; break;
}
}
will output
2x3: 0
0x1: 1
0x1: 2
0x1: 3
0x1: 4
and
php > var_dump(2 xor 3);
bool(false)
php > var_dump(0 xor 1);
bool(true)
Remember that switch cases evaluate the same ==. They're lazy comparisons, not checking types. So your 2 xor 3 is evaluated the same as if the case has been case false, which makes the $i=0 condition match.
Haha, it's quite funny, what you did there.
It's not the switch which gets you into performance troubles. It probably is your for-loop in combination with your switch.
I try to explain it with the second example given.
However, I just have to guess, and so I have to assume that your $this->header array looks like the following (this would be the only reason for your performance leak):
$this->header = array(
999 => 10, // the value is irrelevant, only the key (2) matters
998 => 15
);
Now lets play interpreter debugger.
set $i to 0
is $i<count($this->header)? yes, because header size is 2
is ($i == (0 || 1))? no, because (0 == (0 || 1)) equals (0 == true) equals (false == true) can never be true
is ($i == (2 || 3))? no, because (0 == (2 || 3)) equals (0 == true) equals (false == true) will never comply
next loop, increment $i (set $i to 1)
is ($i<count($this->header)? yes, because header size is 2
is ($i == (0 || 1))? yes, because (1 == (0 || 1)) equals (1 == true) equals (true == true)
go into case statement
set $this->header[1] to -5 (remember the index 1 does not exist so far in your array)
next loop, increment $i (set $i to 2)
is $i<count($this->header)? yes, because header size is 3 (remember? you just added a new index which incremented your header size)
is ($i == (0 || 1))? yes, because (2 == (0 || 1)) equals (2 == true equals (true == true)
go into case statement
set $this->header[2] to -5 (again index 2 did not exist so far)
next loop, increment $i (set $i to 3)
is $i<count($this->header)? yes, because header size is 4 (again, you just added a new index)
Now this will continue until the header size equals $i. In the example above this would happen after 998 iterations, because this would be the first time when there won't be a new index creation (the existing one - 998 - would simply be used), resulting in count($this->header) not changing.
In your first example, this will not happen. The header size will stop to change after the fourth iteration, because the case statement tries to compare integer values instead of booleans. As soon as it reaches index 5 it tries to compare to the values 1, 2, 3 and 4 and will not match a single one, resulting in no new index creation.
To fix the the performance issue, you should make sure that every key in your array exists and also change your for-loop as follows:
$size = count($this->header);
for($i=0; $i<$size); $i++) {...}
Of course this won't fix your logical problems. But since you asked for what is going on, this should be a good explanation, I guess.
var_dump()-ing your $this->header array before and after your loop should prove me right :)
===
Sorry for deleting and undeleting this answer. Just wanted to make sure it really behaves as explained. If you could provide me with a var_dump of your header array, it would be great.
Suppose I have a variable integer and wish to do different things if the value is greater then one value and less then another value. My objective for this switch, is basically to send different results based on the value of $chance, which I will have many cases in the end as this is for a game.
switch ($chance)
{
case ($chance < 15):
echo"strike<br>";
case ($chance < 15 && $chance > 50):
echo"Ball<br>";
break;
case ($chance < 50 && $chance > 100):
echo"Single<br>";
break;
case ($chance <= 150 && $chance >= 100):
echo"double<br>";
break;
case ($chance <= 175 && $chance >= 151):
echo"triple<br>";
break;
case ($chance > 200 && $chance > 175):
echo"Ground Rule Double<br>";
break;
case ($chance < 200):
echo"Home Run<br>";
break;
}
Now, I've been told that I can use conditionals in switch statements, and I've also been told that I should not use them. I really don't know who to believe.
What I do know, is that currently, this switch statement does not work as intended. It doesn't generate syntax errors, but I will get random echos back. This happens when sometimes the chance may be 100 and I will get a home run echo. I'm not sure.
I know I could do the same with a series of if but it would amount to a huge difference in length of code if I can achieve the same results.
I imagine I can do something like
case 1:
echo this
case 2:
echo that
etc etc
Until I hit 2 or 300 but I would like to avoid that if possible.
This is not how you use the switch statement. This is an example of a correct way:
switch ($a) {
case 1:
echo 1;
break;
case 2:
echo 2;
break;
default:
echo 0;
}
For what you want to accomplish you need to use the old if-else statements.
if ($chance < 15)
echo"strike<br>";
else if ($chance >= 15 && $chance < 50)
echo"Ball<br>";
else if ($chance >= 50 && $chance < 100)
echo"Single<br>";
else if ($chance <= 150 && $chance >= 100)
echo"double<br>";
else if ($chance <= 175 && $chance >= 151)
echo"triple<br>";
else if ($chance < 200 && $chance > 175)
echo"Ground Rule Double<br>";
else if ($chance <= 200)
echo"Home Run<br>";
Switch statement syntax:
http://php.net/manual/en/control-structures.switch.php
<?php
switch ($i) {
case 0:
echo "i equals 0";
break;
case 1:
echo "i equals 1";
break;
case 2:
echo "i equals 2";
break;
default:
echo "i is not equal to 0, 1 or 2";
}
?>
To do what you are wanting to do, you should use an if-else. The value used for the case expression must be an integer, floating-point decimal, or string.
You need just set true in you switch. Use switch (true) instead of switch ($chance).
now your code will be:
switch (true)
{
case ($chance < 15):
echo"strike<br>";
case ($chance < 15 && $chance > 50):
echo"Ball<br>";
break;
case ($chance < 50 && $chance > 100):
echo"Single<br>";
break;
case ($chance <= 150 && $chance >= 100):
echo"double<br>";
break;
case ($chance <= 175 && $chance >= 151):
echo"triple<br>";
break;
case ($chance > 200 && $chance > 175):
echo"Ground Rule Double<br>";
break;
case ($chance < 200):
echo"Home Run<br>";
break;
}
Despite some mathematical/comparison issues in your code, it seems that you intend to set numeric ranges that correspond to specific outcomes. It also seems inappropriate to reach multiple outcomes in a single script execution.
Given these truths, you should use an if-elseif-else block. It will be more appropriate and less verbose than a switch block.
The ONLY advantage to using a switch block is when you need to make 1 evaluation and take different actions based on that evaluation. Because you are making multiple evaluations, there is no advantage in using a switch -- in fact, the computational complexity will be the same and the syntax will either be of equal or greater length versus an if block. I personally have such a distaste for switch blocks that I endeavor to use any other viable technique instead. Switch blocks only make very rare appearances in my professional projects.
By progressing in an ASC or DESC fashion, you will only need one expression in each condition. Using consistent operators in each condition will make your script easier to maintain/extend.
Finally, in PHP, elseif is one word not two.
Code:
if ($chance < 0) {
$result = 'Balk'; // ;)
} elseif ($chance < 15) {
$result = 'Strike';
} elseif ($chance < 50) {
$result = 'Ball';
} elseif ($chance < 100) {
$result = 'Single';
} elseif ($chance < 150) {
$result = 'Double';
} elseif ($chance < 175) {
$result = 'Triple';
} elseif ($chance < 200) {
$result = 'Ground Rule Double';
} else {
$result = 'Home Run';
}
echo "$result<br>";