can I do something like
if($x != (y&&z&&r&&w))
Or do I have to write it like this
if($x!=y && $x!=z && $x!=r && x!=w)
Just wondering because I have lots of variables to compare and just wanted a more elegant solution.
You might have a more elegant solution anyway. Here's what I'm trying to do.
foreach($_POST as $key => $value){
if($key != 'category_id'){
$cp[$key] = $value;
}
}
And I have about 6 more variables to compare in my $_POST statement and I would like to make the code pretty. It's basically a huge form that needs to format into a specific array ($cp[]) with specific keys to use my MySQL insert statement.
Any fancy ideas?
Your first portion of code :
if($x != (y&&z&&r&&w))
will evaluate the constants y, z, r and w (strings 'y', 'z', 'r' and 'w', if those constants don't exist) ; doing a AND between each one of those.
And, then, the result of this AND will be compared to $x -- which will be considered as a boolean.
So, no, it's not quite doing what you hoped for ; you must use your second portion of code :
if($x!=y && $x!=z && $x!=r && x!=w)
Note that here, too, it'll search for constants called y, z, r and w (or strings, if those constants still don't exist) -- you should probably put some $ in front of those, if you expect them to be treated as variables.
If you want to test if a variable has one of several values, a possible solution is to put those values into an array, and, then, use the in_array() function :
if (in_array($x, array(10, 20, 30) )) {
// $x is one of those values : 10, 20, 30
}
Some think it's easier to understand this way than writing several comparisons -- I sometimes use this myself, and kind of like it.
You'll have to write the long form or use in_array and an array containing your values.
You you can not do it like this:
if($x != (y&&z&&r&&w))
They have to be separated out in to 4 comparisons.
Alternatively, what you can do is stick the values in an array and have only 1 comparison:
$skip_keys = array('a', 'b', 'c', 'd');
foreach ($_POST AS $key => $value) {
if ( ! in_array($key, $skip_keys)) {
// Continue
}
}
You can't say
if ($x != (1&&2&&3))
like that
I also was wondering in my early years whether we can do
if (1 < $x < 5)
and the answer is no too. But you can use in_array() to test if something in an array for you to check several values at once:
http://php.net/manual/en/function.in-array.php
My recommendation, if you're doing this comparions multiple times, is to write a function that validates your requirements for it. So you'll pass in your '$x' and can compare that to everything you need, and will get a boolean result. The function can be structured nicely with ifs and elseifs and you'll keep your code cleaner.
So, example...
<?php
// random, bad logic, but you get the idea
function validateThisThing($x) {
$toReturn = false;
if ($x == 'this') {
$toReturn = true;
} elseif ($x == 'that') {
$toReturn = true;
}
return $toReturn;
}
Then you can just use that function as needed and keep your checks cleaner and more structured as your function name will bring context into what's being checked.
Related
I am writing some code and I need to compare some values. The point is that none of the variables should have the same value as another. For example:
$x=1
$y=2
$z=3
if ($x != $y and $y != $z and $x != $z) {
#do something
}
Now, it is easy to see that in a case of code with more variables, the if statement becomes very long and full of ands. Is there a short way to tell PHP that no 2 variable values should be the same.
You could put all the values in an array and check if the length of the array was the same as the length of only the unique values in the array:
if (count(array($x, $y, $z)) == count(array_unique(array($x, $y, $z)))) {
// all values different. do something
}
Demo on 3v4l.org
Is there a shorthand way of writing the code below?
if (($tstat=='no_prices')&&($l1stat=='no_prices')&&($l2stat=='no_prices')&&($l3stat=='no_prices'))
{
//do something
}
I tried using the below code,but it did something when one of the variables was not equal to 'no_prices'.
if (($tstat && $l1stat && $l2stat && $l3stat)=='no_prices')
{
//do something
}
To check that the strings weren't causing problems I tried substituting 0 for 'no_prices' and 1 for other values, but the result was the same.
array_flip is several times faster than array_unique:
function all_equal($arr, $value) {
return array_keys(array_flip($arr)) == array($value);
}
$arr = array($tstat, $l1stat, $l2stat, $l3stat);
echo all_equal($arr, 'no_prices');
A quick profile for the answers given thus far, for 1000 iterations on array length 1000:
array_flip: 0.07321620 seconds
array_unique: 0.32569408 seconds
foreach: 0.15136194 seconds
array_filter: 0.41404295 seconds
The code used to profile is here: http://codepad.org/szgNfWHe
Note: As #cypherabe rightly points out, array_flip does not overtake array_unique until the array has at least 5 elements, and does not overtake foreach until the array has at least 10 elements.
Unless I'm mistaken, there's no native way of doing this. If this is something that you have to check for often, try using a custom function for it, e.g.:
function allEquals($chkstr, $vals) {
if (!is_array($vals)) { die('allEquals() $vals not an array'); }
foreach ($vals AS $v) {
if ($chkstr != $v) { return false; }
}
return true;
}
My first idea would go into PHP's Array API:
// $tstadt, $l1stat, … are all "no_prices"
$isAllNoPrice = array_unique(array($tstat, $l1stat, …)) == array("no_prices"));
if ($isAllNoPrice) {
// …
}
Documentation is mandatory otherwise nobody (including yourself) will understand the code.
If efficiency might be a concern others pointed out that array_unique() seems to be slow. Using the keys of the hash table would be a next approach:
// $tstadt, $l1stat, … are all "no_prices"
$varsMap = array(
$tstat => null,
$l1stat => null,
// …
);
if (array_keys($varsMap) == array("no_prices")) {
// …
}
But now the wall of code is growing. PHP offers one operator which nearly does what you want and is chainable: &
$v1 = "no_prices";
$v2 = "no_prices";
$v3 = "no_prices";
var_dump(($v1 & $v2 & $v3) == "no_prices"); // bool(true)
$v3 = "prices";
var_dump(($v1 & $v2 & $v3) == "no_prices"); // bool(false)
I said it nearly does what you want: There are cases in which you will have false positives:
$v1 = 1;
$v2 = 1;
$v3 = 3;
var_dump(($v1 & $v2 & $v3) == 1); // bool(true)
For Strings it seems to cut the bitmask to the shortest string:
$v1 = "abcd";
$v2 = "ab";
$v3 = "abc";
var_dump($v1 & $v2 & $v3); // "ab"
var_dump(($v1 & $v2 & $v3) == "ab"); // bool(true)
So I don't recommend this as a general purpose solution. Only if you know (=unit tested) that your values are in a set where no combination never results to a false positive (e.g. {"dog", "cat", "horse"}) you might consider this solution. I gave it a second thought and must say don't use that at all. Imagine how your colleagues will love you for searching a bug introduced by that method.
In your case you can do:
if (count(array_unique($tstat, $l1stat, $l2stat, $l3stat)) == 1 //Check if all share the same value (i.e., number of unique values is 1
&& $tstat == 'no_prices')) //If everything is the same and $stat == 'no_prices', then everything is 'no_prices'
{
}
<?php
$tstat = $l1stat = $l2stat = $l3stat = 'no_prices';
$testVars = array($tstat,$l1stat,$l2stat,$l3stat);
if(count(array_filter($testVars, function($x) { return $x === 'no_prices'; })) == count($testVars))
{
print("Correct");
}
Use array_filter with a anonymous callback, and check if its length is greater is equal to original array i.e. all conditions passed,
or if length is greater than zero i.e. any one condition passed
No, this code won't work:
if (($tstat&&$l1stat&&$l2stat&&$l3stat)=='no_prices')
{
//do something
}
Why? Because condition in parentheses, will check result itself - You are comparing boolean to string. So in pseudo-code, thats what your code looks like:
if ( ($tstat is true, $l1stat is true, $l2stat is true, $l3stat is true) == 'no_prices' )
^ whole thing returns true ^ ^ true ^
If you wan't to achieve this, you can use count() and array_unique():
if ($tstat == 'no_prices' && count(array_unique(array($tstat, $l1stat, $l2stat, $l3stat))) == 1)
try this:
$arr = array($tstat,$l1stat,...); //make an array
$arr =array_unique($arr);//unique this array
if(count($arr) == 1 && $arr[0] = 'no_prices'){ // check if only one array element have with same value
echo "got it";
}
demo example
The answer is "no". There's no shorthand to the given condition that will make your code more readable, which should be your top priority. You can improve it though:
define('MYAPP_NO_PRICES', 'no_prices');
if ($tstat === MYAPP_NO_PRICES
&& $l1stat === MYAPP_NO_PRICES
&& $l2stat === MYAPP_NO_PRICES
&& $l3stat === MYAPP_NO_PRICES) {
// do something
}
Having all these vars to check individually is a code smell; you might want to rethink this design so you never have to do this.
Im not great in php and I could do with a little help. I want to say something like
if ($x == 1 or 2 or 3 or 4) {do function}
but the only way i know how to do that is to go
if (($x == '1') or ($x == '2')) or...
which seems a long way of doing it. Is there a better way I am missing, like
if ($x == 1,2,3,4) {do}
Thanks for your answers!
you can use in_array function
$array = array(1,2,3,4)
if(in_array($x, $array)) {
// do something
}
switch ($x) {
case 1:
case 2:
case 3:
case 4:
// do
break;
}
Or you can use the in_array() function creating an array such as $a = array(1,2,3,4); and then do if (in_array($x, $a)).
If you are concerned about space, you can also use the shortcut:
if (in_array($x, array(1,2,3,4))) { /* do */ }
You can create an array of expected values and then use function in_array().
http://php.net/manual/en/function.in-array.php
If it's a range, you could do:
if ($x >= 1 && $x <= 4) { }
You could also construct an array and check if the number is in that array.
<?php
$data = array(1,2,3,4);
if(in_array($x, $data)){
// execute function
}
?>
All the above ideas are good. I am going to show another way, that is not better, but is different.
You can store comparations in variables, to use later or combine. This helps readability, and make complex expresions easy to create and read. It obviusly remove any repetition.
$is_number = ($str=="one" or $str=="two" or $str=="tree");
$is_english = ($str=="one" or $str=="horse");
$is_french = ($str=="baguette" or $str=="amie");
$is_fun = $is_french or $is_english;
if($is_french and !$is_number){ ... }
I am trying to write would be a simple if condition.
function genderMatch($consumerid1, $consumerid2)
{
$gender1=getGender($consumerid1);
$gender2=getGender($consumerid2);
echo $gender1;
echo $gender2;
if($gender1=$gender2)
echo 1;
return 1;
else
echo 0;
return 0;
}
The output of the getGender function is either a M or F. However, no matter what I do gender1 and gender2 are returned as the same. For example I get this output: MF1
I am currently at a loss, any suggestions?
if ($gender1 = $gender2)
assigns the value of $gender2 to $gender1 and proceeds if the result (i.e. the value of $gender2) evaluates to true (every non-empty string does). You want
if ($gender1 == $gender2)
By the way, the whole function could be written shorter, like this:
function genderMatch($cid1, $cid2) {
return getGender($cid1) == getGender($cid2);
}
You have to put two == for comparison. With only one, as you have right now, you are assigning the value to the first variable.
if($gender1=$gender2)
would become
if($gender1==$gender2)
this:
if($gender1=$gender2)
should be
if($gender1==$gender2)
notice the extra ='s sign. I think you might also need curly brackets for multiple lines of an if/else statement.
Your using the assignment operator = instead of comparsion operators == (equal) or === (identical).
Have a look at PHP operators.
You have some structural problems with your code as well as an assignment instead of a comparison.
Your code should look like this:
function genderMatch($consumerid1, $consumerid2){
$gender1=getGender($consumerid1);
$gender2=getGender($consumerid2);
echo $gender1;
echo $gender2;
if($gender1==$gender2){
echo 1;
return 1;
}else{
echo 0;
return 0;
}
}
Notice the double '=' signs in the if statement. This is a comparison. A single '=' is an assignment. Also, if you want to execute more than 1 line of code with an if/else, you need brackets.
You are using a single = which sets the variable, ie. the value of $gender1 is set to be the value of $gender2.
Use the === operator instead: if($gender1 === $gender2). It is usually a good idea to do strict comparisons rather than loose comparisons.
Read more about operators here: php.net
Another alternative is to use strcmp($gender1, $gender2) == 0. Using a comparer method/function is more common in languages where the string-datatype isn´t treated as a primary data-type, eg. C, Java, C#.
Okay, I believe that I can simplify this line of code except I can't find anything online. Can anyone help me?
if(empty($action) || $action == "a" || $action == "b" || $action == "c") {
}
Thanks!
You can use in_array() to search an array of possible values for $action:
if (empty($action) || in_array($action, array('a', 'b', 'c'))) {
}
I keep the empty() condition separate because empty() tests true for a number of things besides the empty string ''.
If all you care is to test for the empty string, you can include it in in_array(), and get rid of that empty():
if (in_array($action, array('', 'a', 'b', 'c'))) {
}
Performantly, I think explicitly including empty() is a teeny weeny little bit better, due to short-circuiting.
$options = array("a", "b", "c");
if (empty($action) || in_array($action, $options) ) {
}
I suggest you don't simplify this code because you may gain some kind of readability but you would also increase computation time. And that's a thing I would prefer to improve more than readability (code is executed a lot more often than read in plain text).
Why is that?
An expression like yours consisting only of or conjunctions will end right the moment the first 'true' value is found. So in best case PHP will just evaluate empty($action) with true and leave the if-header without evaluating all the other parts. In worst case it will check every part till the end. So in average - without further knowlege about the data you will check - you are running and computing half of the if-header.
But if you use something like in_array($action, array('a', 'b', 'c')) than you will construct the whole array with all elements and search in it. So your PHP interpreter has to create all the elements and the array just to match one of the first ones. Which is anyway more computation than your current line.
So think twice about readabilty vs. code complexity.
if (empty($action) || preg_match('/^[abc]$/', $action)) { ... }
Edit: empty($action) is needed to allow false, array(), 0, and null to pass which you may not want.