Some php coding about array_search with unexpected result - php

i want to find a key value from a array, if not exist then insert a array set into a array list
If i search blue, it will return Y
But if i search green, return N
$people = array(
0 => array(
'name' => 'John',
'fav_color' => 'green'
),
1=> array(
'name' => 'Samuel',
'fav_color' => 'blue'
)
);
$found_key = array_search('green', array_column($people, 'fav_color'));
if($found_key){
print_r("Y");
}else{
print_r("N");
}
Expect search blue or green return Y

As per note written in the documentation of array_search:
Warning: This function may return Boolean FALSE, but may also return a
non-Boolean value which evaluates to FALSE. Please read the section on
Booleans for more information. Use the === operator for testing the return value of this function.
In Your case, green value has index 0. In if statement 0 means false. To get this rid of this problem, you need to strict type check the value returned by array_search as below.
if ($found_key !== false) { // strict type check
print_r("Y");
} else {
print_r("N");
}
Demo

You can Use in_array() function also.
$people = array(
0 => array(
'name' => 'John',
'fav_color' => 'green'
),
1=> array(
'name' => 'Samuel',
'fav_color' => 'blue'
)
);
$found_key = in_array('green', array_column($people, 'fav_color'));
if($found_key){
print_r("Y");
}else{
print_r("N");
}

Related

Sum column values but only if specific key exists in same row

I need to sum the price values of all rows where the optional check element exists.
Sample data:
[
6254 => [
'check' => 'on',
'quantity' => 2,
'name' => 'Testing product_special One Size',
'total' => 15.9,
'price' => 33.0000,
'totalken' => 33075.9,
],
6255 => [
'quantity' => 1,
'name' => 'Testing card',
'total' => 113.85,
'price' => 33.0000,
'totalken' => 16537.95,
],
6256 => [
'check' => 'on',
'quantity' => 1,
'name' => 'Testing food',
'total' => 113.85,
'price' => 33.0000,
'totalken' => 16537.95,
],
]
I tried array_sum(array_column($value, 'price')) but this sums all price values regardless of the check value.
Expected result: 66
I would use array_reduce in this case.
array_reduce loops through the array and uses a callback function to reduce array to a single value.
<?php
$totalPrice = array_reduce($myArray, function ($accumulator, $item) {
// I'm checking 'check' key only here, you can test for 'on' value if needed
if (isset($item['check'])) {
$accumulator += $item['price'];
}
return $accumulator;
});
You can simply filter the array based on condition by using array_filter() function of php.
You can see the usage of array_filter() here.
Here is my solution for you if you want to use condition.
$filteredByCheck = array_filter($value, function ($val){
return isset($val['check']);
});
$total = array_sum(array_column($filteredByCheck, 'price'));
The quickest method would be just to loop over the array and maintain a sum, use ?? '' to default it to blank if not set...
$total = 0;
foreach ($value as $element ) {
if ( ($element['check'] ?? '') == "on" ) {
$total += $element['price'];
}
}
#aliirfaan's implementation of array_reduce() can be modernized and compacted as the following snippet.
Code: (Demo)
echo array_reduce(
$array,
fn($result, $row) =>
$result + isset($row['check']) * $row['price']
);
The above uses arrow function syntax which is available since PHP7.4. The mathematics in the return value of the custom function multiplies the price value by the true/false evaluation of isset() on the check column. The boolean value is coerced to an integer automatically when used with arithmetic -- false is zero and true is one. If the coercion is not to your liking, you can explicitly cast the boolean value using (int) immediately before isset().

Why am I getting a different, negative value from array than I set?

I have an array of tests for a function:
$testArray = array(
(object)array(
"value" => 12345678901,
"expected" => "123456789012"
),
(object)array(
"value" => "1234567890",
"expected" => false
),
(object)array(
"value" => (int)12345678901,
"expected" => "123456789012"
),
(object)array(
"value" => 1234567890,
"expected" => false
),
(object)array(
"value" => "12345678901",
"expected" => "123456789012"
),
(object)array(
"value" => "123456789012",
"expected" => "123456789012"
),
(object)array(
"value" => "123456789013",
"expected" => false
),
(object)array(
"value" => "1234567890128",
"expected" => "1234567890128"
),
(object)array(
"value" => "1234567890127",
"expected" => false
),
(object)array(
"value" => array(),
"expected" => false
),
(object)array(
"value" => (object)array(),
"expected" => false
),
(object)array(
"value" => array("1234567890127"),
"expected" => false
),
(object)array(
"value" => (object)array("1234567890127"),
"expected" => false
)
);
I run the array through a foreach loop to see which ones work to test a function, and most of them work. The third one should return 123456789012 but instead it returns "-539222987" when I get the value. Why is this happening when the rest work just fine?
Here is the foreach loop. The validUPC function just looks at the upc and makes sure it is a valid one.
foreach($testArray as $key => $test) { // Test each value
$result = App::make("Product")->validUPC($test->value);
var_dump($result);
echo "Result from array member $key was: $result\n";
if($result !== $test->expected) { // Check against expected value
echo "Test FAILED\n";
$success = false; // Returns false if any of them failed
}
else {
echo "Test passed\n";
}
}
The validUPC function begins like this:
public function validUPC($upc = "non") {
try {
// If there is no upc specified, get the product upc
if($upc == "non") {
$upc = $this->upc;
}
// No arrays allowed
if(is_array($upc)) {
return false;
}
// Make it a string
$upc = (string)$upc;
var_dump($upc);
Which returns something like this:
Product.php:99:float 12345678901
Product.php:101:string '12345678901' (length=11)
CatalogTest.php:70:string '123456789012' (length=12)
Result from array member 0 was: 123456789012 Test passed
Product.php:99:string '1234567890' (length=10)
Product.php:101:string '1234567890' (length=10)
CatalogTest.php:70:boolean false
Result from array member 1 was: Test passed
Product.php:99:int -539222987
Product.php:101:string '-539222987' (length=10)
CatalogTest.php:70:boolean false
Result from array member 2 was: Test FAILED
Without seeing the code in detail, I'll speculate.
On a 32-bit platform, the largest representable integer is 231-1, or 2,147,483,647. The integer you present - 123456789012 - is larger than that. When you give an integer larger than the maximum, PHP, like other languages, overflows the number into a value it can represent. In your case, it's -539222987.
I'd recommend checking that your code's not trying to work with integers larger than PHP_INT_MAX on your platform.
Responding to the comments: PHP converts integers larger than those representable by the available bits to a double. But if you then cast that double to an int, you enter what looks like a wrap-around. On a 64 bit system, for example:
$a = pow(2, 65); // 65 === (PHP_INT_SIZE * 8) + 1
var_dump($a);
$b = (int)$a;
var_dump($b);
$c = $b - 100;
var_dump($c);
Mathematically, we expect $c === 36893488147419103132. It is not. The output is:
float(3.6893488147419E+19)
int(0)
int(-100)
The floating point is approximately the exact value: we've traded precision in the lower bits for the ability to continue working with the value as a number. But then when we force PHP to treat it as an integer, it gives up and truncates it toward 0 - but the behavior is undefined, so don't rely on it always being exactly 0: all hell has broken loose at point.
Worse, there is no warning, no notice raised. So how do you guard your code against this scenario? I urge use of strict_types. When you expect to be working with precisely an int, define your functions to take them. If you then calculate a value that over- or underflows, you'll get a float, which will pass into your strictly int method, which then will notify you.
If you need to work with big integers, there are libraries for that.

why it returns empty value but of boolean type when no match is found

I am using the following code to search an element inside a multi dimensional array.When a match is found it returns the index.But when no match is found it returns a empty value.Not 0 or 1.But if i print out the type , it says boolean.What does that boolean mean if it returns empty.Does it mean that it will be equal to empty string ?
$arr =Array
(
0 => Array
(
'uid' => '100',
'name' => 'Sandra Shush'
),
1 => Array
(
'uid' => '5465',
'name' => 'Stefanie Mcmohn'
),
2 => Array
(
'uid' => '40489',
'name' => 'Michael'
)
);
$match = array_search('546',array_column($arr, 'uid'));
echo gettype($match);
If you take a look at array_search method description http://php.net/manual/ro/function.array-search.php it says: Returns the key for needle if it is found in the array, FALSE otherwise. There is your answer.
http://php.net/manual/en/function.array-search.php
This function may return Boolean FALSE, but may also return a non-Boolean value which evaluates to FALSE. Please read the section on Booleans for more information. Use the === operator for testing the return value of this function.
When converting to boolean, the following values are considered FALSE:
the boolean FALSE itself
the integer 0 (zero)
the float 0.0 (zero)
the empty string, and the string "0"
an array with zero elements
the special type NULL (including unset variables)
SimpleXML objects created from empty tags
Every other value is considered TRUE (including any resource and NAN).
array_search() function returns the key for needle if it is found in the array, FALSE otherwise. So when you are using gettype() on the return value, then it will return the type of FALSE i.e. BOOLEAN for unsuccessful search, otherwise INT index value.
your code is working , when array_search not found then return false and if gettype($match); then show boolean and if found then return index so in this case return integer
this is code which return
<?php
$arr =Array
(
0 => Array
(
'uid' => '100',
'name' => 'Sandra Shush'
),
1 => Array
(
'uid' => '5465',
'name' => 'Stefanie Mcmohn'
),
2 => Array
(
'uid' => '40489',
'name' => 'Michael'
)
);
$match = array_search('5465',array_column($arr, 'uid'));
echo gettype($match);
and output is: integer
this is normal example
<?php
$array = array(0 => 'blue', 1 => 'red', 2 => 'green', 3 => 'red');
$key = array_search('green', $array); // $key = 2;
$key = array_search('red', $array); // $key = 1;
?>
for more information
http://php.net/manual/ro/function.array-search.php
array_search() returns FALSE when it cannot find the needle in the haystack.
The comparison is done using ==. This means, the values are converted to the same type, if needed. But their values must be the same after conversion. It doesn't match substrings.
echo(FALSE); doesn't print anything. The type of FALSE is boolean, indeed. And FALSE is == with the empty string (''), zero (0), the string that contain the number zero ('0') and other empty values.

Unset the key in multidimensional array is not working

I am trying to unset the key which is equal to 'null' in my multidimensional array but the codes I've work with is not working so I tried to run it online. But even in online it does not work so I think there is something wrong in my codes.
My link for code is https://eval.in/591584
And this is my array:
$array = array(
'6' => array(
'null' =>array(
'null'=>array(
'11:04'=>array(
'id' => '22'
)
)
),
'1'=>array(
'2'=>array(
'11:04'=>array(
'id' => '22'
)
)
),
)
);
What I want is to remove the key with name null.
The output I want is below where the null key is unset:
$array = array(
'6' => array(
'1'=>array(
'2'=>array(
'11:04'=>array(
'id' => '22'
)
)
),
)
);
The code I've done so far is:
foreach($array as $devp => $dev){
foreach($dev as $comp => $com){
if($comp == null){
unset($array[$devp][$comp]);
}
}
}
But it's not working. I declared this condition ($comp == null) as comparing If $comp is equal to null. It should unset the array. What am I missing please help me.
In PHP null is a special datatype. And your key with value 'null' is a string.
So proper comparison is:
if ($comp == 'null') { // see quotes?
// do something
}

php filter var returning a wrong result

I wanted to use the php filer_var function but it's returning a wrong result, it seems that it doesn't take into account the range:
$v = 54;
$int_opts = array (
'min_range' => 0,
'max_range' => 24
);
if ( filter_var($v, FILTER_VALIDATE_INT, $int_opts) ) echo 'an integer';
else echo 'not an integer';
This shouldn't be an integer as 54 is not between 0 and 24, but it returns true and echoes "an integer".
What's the problem here?
Thanks.
The "options" array needs to have a member named "options". From the manual:
$options = array(
'options' => array(
'default' => 3, // value to return if the filter fails
// other options here
'min_range' => 0
),
'flags' => FILTER_FLAG_ALLOW_OCTAL,
);
you're not passing that so the behaviour displayed is okay.
$options = array();
$options['options']['min_range'] = 0;
$options['options']['max_range'] = 24;
$options['flags'] = FILTER_FLAG_ALLOW_OCTAL;
var_dump(filter_var(54, FILTER_VALIDATE_INT, $options)); //bool(false)
var_dump(filter_var(21, FILTER_VALIDATE_INT, $options)); //int(21)
It works this way.
About FILTER_FLAG_ALLOW_OCTAL:
Regards inputs starting with a zero (0) as octal numbers. This only allows the succeeding digits to be 0-7. According to this:
var_dump(filter_var(06, FILTER_VALIDATE_INT, $options)); //int(6)
var_dump(filter_var(09, FILTER_VALIDATE_INT, $options)); //int(0)
Version 5.3.8 purports to have fixed bug #47745 which meant that FILTER_VALIDATE_INT wasn't allowing a minimum integer.
The file you might want to check is ext/filter/logical_filters.c
void php_filter_int(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
{
....

Categories