PHP Native "Count Set" Function - php

I have run into a point in my code where I would like to check if, within a dynamically set array, there are at least two set values before performing certain tasks. I cannot find a native PHP function which accomplishes this. Count returns all values, but does not allow me to check for the "truthiness" of the array values. Is there an equivalent native function for the following code:
function count_set($array = array()){
$count = 0;
foreach($array as $key => $value){
if($value){
$count++;
}
}
return $count;
}

Truthy scalar values are NOT false, 0, null, string 0 or an empty string (see Converting to boolean). array_filter() will remove these by default if you don't provide a callback:
$count = count(array_filter($array));

Related

MySQL weird behavior with null integer

So I'm trying to implement php-etl to my application and MySQL doesnt let me insert null to nullable integer but it does if I manually change it, like this:
### This works ###
foreach($data as $row){
if($row["some_integer"] == Null){
$row["some_integer"] = Null;
}
if($row["some_other_integer"] == Null){
$row["some_other_integer"] = Null;
}
MyModel::create($row);
}
### This throws General error: 1366 Incorrect integer value ###
foreach($data as $row){
MyModel::create($row);
}
Tried both manually and with marquine/php-etl package. The input is csv file, null is empty space between ;; separators. Anybody knows what is going on here? Working on laravel 7.
Ok so the package loads the values as empty strings and by setting it Null it becomes real null... Is there a way to quicky convert these values to null?
MySQL won't treat an empty string as null, simply because an empty string and null are two different things. So the message you get from MySQL isn't weird, it's correct.
Nullify all empty strings in an array
If you just want to nullify all empty strings in an array, you can create a simple function for it:
function nullifyEmptyStrings(array $array)
{
return array_map(function ($item) {
return $item !== '' ? $item : null;
}, $array);
}
Then call it where ever/when ever you need it:
$row = nullifyEmptyStrings($row);
or use it directly in the argument for the create function:
MyModel::create(nullifyEmptyStrings($row));
Here's a demo
Nullify specific empty strings in an array
If you want to be able to define which array items to nullify, you can use this function:
function nullifyEmptyArrayValues(array $array, array $keys)
{
foreach ($keys as $key) {
if (array_key_exists($key, $array) && $array[$key] === '') {
$array[$key] = null;
}
}
return $array;
}
And in your code, you first pass the array containing the data and then another array with the keys to nullify, if the values are empty:
$row = nullifyEmptyArrayValues($row, ['some-key', 'another-key']);
Here's a demo

Function works inconsistently [duplicate]

This question already has answers here:
How to use return inside a recursive function in PHP
(4 answers)
Closed 9 months ago.
I am new to PHP. I have a function that works (the value printed to the screen from within the function is exactly what I expect), but only sometimes returns the answer (other times it returns NULL). I believe I have isolated the error to something involving my use of the static feature of PHP, but I am not sure how exactly I'm transgressing/how to fix it. I tried to work around it by creating a new non static variable to store the result, and that improved my code from always returning NULL to only sometimes returning NULL. The erring function is part of a larger suite of programs I wrote, so I'll include it and the testing function I use to check that it works.
probGen.php
<?
require_once("randX.php");
require_once("../displayArray.php");
error_reporting(E_ERROR | E_WARNING | E_PARSE);
function probGen(array $arr, float $control = 0.01)
/*
* Generates a valid, random probability distribution for a given array of elements, that can be used in conjunction with "probSelect()".
* Input:
$arr: An array of elements.
$control: A value that decides how much mass is allowed to be unilaterally dumped onto one element. A high value would permit distributions where most of the mass is concentrated on one element.
If an invalid value is provided, the default is used.
* Output: An associative array where the keys are the elements in the original array, and the values are their probabilities.
*/
{
$control = ($control <= 1 && $control >= 0)?($control):(0.01); #Use the default value if an invalid number is supplied.
static $result = []; #Initialises $result with an empty array on first function call.
static $max = 1; #Initialises $max with 1 on first function call.
foreach ($arr as $value)
{
$x = randX(0, $max); #Random probability value.
$result[$value] = ($result[$value] + $x)??0; #Initialise the array with 0 on first call, and on subsequent calls increment by $x to assign probability mass.
$max -= $x; #Ensures that the probability never sums to more than one.
}
print("<br>sum = ".array_sum($result)."<br><br>");
displayArray($result);
/*
* After the execution of the above code, there would be some leftover probability mass.
* The code below adds it to a random element.
*/
$var = array_values($arr);
if($max <= $control) #To limit concentration of most of the probability mass in one variable.
{
$result[$var[rand(0,(count($var)-1))]] += $max; #Selects a random key and adds $max to it.
displayArray($result);
print("<br>sum = ".array_sum($result)."<br><br>");
$sol = $result;
return $sol;
}
else
probGen($arr, $control);
}
?>
test.php
<?
/*
* This file contains some functions that can be used for assigning probabilities to an array of elements or selecting an element from said array with a given probability.
*/
require_once("../displayArray.php");
require_once("confirm.php");
require_once("randX.php");
require_once("probGen.php");
require_once("probSelect.php");
$test = ["California" => 0.37, "Florida" => 0.13, "New York" => 0.28, "Washington" => 0.22];
$testX = array_keys($test);
var_dump(probGen($testX));
/*for ($i=0; $i < 100 ; $i++)
{
print(var_dump(confirm(probGen($testX))));
}*/
?>
Screenshot of probGen() working as intended:
Screenshot of probGen() failing:
From testing I've been able to determine that probGen() fails if the recursion occurs more than once.
As #aynber comment (all credit to him I just wrote that so this post will have an answer).
When calling the recursive call you should add return (at the last line) in order to bubble the return value of probGen function as return probGen();
Generally speaking, having PHP return NULL sometimes may use as hint to case when non value is being returned.
Can see also this question with same issue.

PHP - set all empty or null in an array, to 0, without a foreach loop

I'm working with a large array. We're displaying all fields of data in the array with a table. Some fields in the array are null because the user hasn't accumulated anything in that field. However, we wanted a zero for when they have such a result. Our solution was to display the value along with intval()
intval(#$users[$user_id]['loggedin_time'])
Which is fine, but it is ugly and inelegant. Is there a way, without a foreach loop, to set all values of '' in the array to be 0?
Yes, with array_map:
$input = array(...);
$output = array_map(function($item) { return $item ?: 0; }, $input);
The above example uses facilities of PHP >= 5.3 (inline anonymous function declaration and the short form of the ternary operator), but you can do the same in any PHP version (only perhaps more verbosely).
You should think a bit about the conditional inside the callback function; the one I 'm using here will replace all values that evaluate to false as booleans with zeroes (this does include the empty string, but it also includes e.g. null values -- so you might want to tweak the condition, depending on your needs).
Update: PHP < 5.3 version
It's either this:
function callback($item) {
return $item == false ? 0 : $item;
}
$output = array_map('callback', $input);
Or this:
$output = array_map(
create_function('$item', 'return $item == false ? 0 : $item;'),
$input);
I assume you are retrieving this information from a database of some sort.
If you are getting the array from a Mysql Table try something like this:
http://forums.mysql.com/read.php?20,36579,36579#msg-36579

Check if an array contains a specific value?

I'd like to check if there is a value on an array like this:
function check_value_new ($list, $message) {
foreach ($list as $current) {
if ($current == $message) return true;
}
return false;
}
function check_value_old ($list, $message) {
for ($i = 0; $i < count ($status_list); $i ++) {
if ($status_list[$i] == $$message) return true;
}
return false;
}
$arr = array ("hello", "good bye", "ciao", "buenas dias", "bon jour");
check_value_old ($arr, "buenas dias"); // works but it isn't the best
check_value_new ($arr, "buenas dias"); // argument error, where I'm wrong?
I've read the check_value_new method is a better way to work with arrays, but I'm not used to work with it, how I should fix it?
PHP offers a function called in_array that checks if a value exists in a given array.
You can change your check_value_new function to include this:
function check_value_new ($list, $message) {
foreach ($list as $current) {
if (in_array($message, $current)) {
return true;
}
return false;
}
If you'd like to, you could also make the function work without the foreach loop, like so
function check_value_new ($list, $message) {
// returns true if found, else returns false.
return in_array($message, $list);
}
The reasons that your check_value_old() function breaks is because you have a typo in your loop's second parameter. $status_list is not one of the variables passed into your function and it is not declared anywhere before it is used. You merely need to use $list instead. It is also not necessary to call count() on every iteration -- since that value never changes in the loop, just call it once before the loop and use that value in the second parameter.
As for deciding how to loop over array values, there is no reason to reinvent a native function call. in_array() was already designed and optimized to search linear values in an array and return true as soon as it finds a match; otherwise it returns false.
I don't know what #AnthonyForloney is doing by writing in_array() inside of a foreach() loop. Not only will the snippet break because there aren't enough curly braces, the input array does not have two levels of data, so in_array() will choke when it receives $current which is a string (not the expected array).
Ultimately, my advice is: Only write your own custom function when there isn't a native function to suit your needs. Throw away both of the manual looping ideas and only call:
$arr = ["hello", "good bye", "ciao", "buenas dias", "bon jour"];
var_export(in_array("buenas dias", $arr));
One final insight that I'd like to provide is regarding microoptimization. If you are planning to check the existence of a unique value in a "very large" array, or if you are going to be making thousands of searches on the same array, then it would be more efficient to set up your array in a "flipped" orientation and call isset() or array_key_exists(). isset()/array_key_exists() will always outperform in_array() or array_search() because of the way that php handles arrays as "hash maps". More reading here.

PHP array searching question

I have arrays, some are multidimensional as well. I need a way to know if all the values are NULL. What would be the most efficient and effective way of determining if ALL values of an array (as well as the values of the arrays within that array) are NULL?
So basically: search array, if all values are NULL, $flag = true
EDIT: The values are being pulled from a MySQL database where NULL is in the context of MySQL, if that makes a difference.
If i remember well db null fields become empty strings in php so you can use a function like this:
function isEmptyArray($array){
foreach($array as $val)
if((is_array($val) && !isEmptyArray($val))||(!is_array($val) && $val!="")) return false;
return true;
}
Depends on what would you use that flag for, but I think the best would be to query the database so it retrieves only non null values, like
select col1,col2,col3 from table where col1 is not null and col2 is not null
and col3 is not null
That said, a simple way to do something like that in PHP would be
//array_filter filters values that evaulate to fals
$result = array_filter($input);
if (count($result) == 0) { $flag = true; }
This will fail for multidimensional arrays and if zeroes or other values that get automatically converted to false are valid values in your array, if this is the case you have to build a recursive callback function and pass it as a second parameter to array_filter.
You may want to look at the array_filter() function, by default it strips out values that equate to false (this includes NULL).
I'm not sure if it'll work as is for mutli-dimensional arrays, but it has the option to use call back functions which would easily allow you to handle that.
Long story short, if you run array_filter on the array and you get an empty array returned then all your values are Null or equal to false - if you need to differentiate between these values in a strict sense, then you should use a call back.
Can be done recursively:
arrayIsFullyNull ($arr)
{
if (is_array($arr))
foreach ($arr as $val)
if (!arrayIsFullyNull($val))
return false;
else if (!is_null($arr))
return false;
else
return false; // it's not null, and not array => value
return true;
}
You could use a RecursiveArrayIterator to walk over all the values (leaves of the tree of of nested arrays).
Untested code:
function isNullOrNestedArrayOfNulls($array)
{
if (is_null($array)
{
return true;
}
else if (!is_array($array))
{
return false;
}
$allNull = true;
$iter = new RecursiveIteratorIterator(new RecursiveArrayIterator($array),
RecursiveIteratorIterator::LEAVES_ONLY);
while ($iter->valid())
{
if (!is_null($iter->current())
{
$allNull = false;
break;
}
}
return $allNull;
}
This would have the advantage of avoiding a recursive function (which have the reputation of being rather inefficient in PHP).

Categories