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).
Related
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
So I've got a while loop, inside I have $array_collections that gives me 35 value per loop, I want to verify for every value if it's equal to NULL then give it an empty string. I did that :
while ($array_collections = tep_db_fetch_array($query)) {
foreach ($array_collections as $key => $value) {
if (is_null($value)) {
$array_collections[$key] = "";
}
}
$docs[] = new \Elastica\Document('', \Glam\HttpUtils::jsonEncode(
array(
'X' => $array_collections['X'],
... etc
)));
}
This technically should work, but the loop goes over 500K elements so it's huge, and for every element we put it into a table, problem is that I run out of memory at some point. So is there another simple way to give any given NULL value an empty string without looping?
well, you can put NOT NULL constraint with empty string as DEFAULT value in the DB for that so you dont need to do that in php using looping, but if you dont want to change the DB design then you can use COALESCE in your query
select COALESCE(yourfield,'') from table
it will convert NULL value into empty string
You can use array_map function to replace null values into empty string.
$array_collections=array_map(function($ar)
{
if(isset($ar) && $ar!=null){
return $ar;
}
return '';
},$array_collections);
Above code replace all null values to empty string. No need of loop.
you can use array_walk:
function replace_null(&$lsValue, $key) {
if(is_null($lsValue)) {
$lsValue = "";
}
}
array_walk($array_collections, 'replace_null');
I need to ensure that all the elements in my array are empty strings to process an action. The way I am currently doing it is incrementing a variable each time an element is an empty string. Then I check the value of that variable against a certain requirement N. If N is met, the action is processed. Below is the snippet of the code that checks for empty strings. I am not sure if this is the best way to do it and think there has to be a better way to do it because basically I am hard coding that value N. Can anybody else suggest another approach?
function checkErrorArray($ers) {
$err_count = 0;
foreach ($ers as &$value) {
if ($value == '') {
$err_count++;
}
}
return $err_count;
}
Why don't you do:
function areAllEmpty($ers) {
foreach ($ers as &$value) {
//if a value is not empty, we return false and no need to continue iterating thru the array
if (!empty($value)) return false;
}
//if got so far, then all must be empty
return true;
}
It will not have to run through the whole array if a non-empty value is found.
You could also do a shorter version:
function areAllEmpty($ers) {
$errs_str = implode('', $ers);//join all items into 1 string
return empty($errs_str);
}
Hope this helps.
Just filter it and if it is empty then ! will return true if not empty it will return false:
return !array_filter($ers);
Or if you actually need the count of empty elements then:
return count(array_diff($ers, array_filter($ers)));
We gave a given array which can be in 4 states.
array has values that are:
only arrays
only non-arrays
both array and non array
array has no values
Considering than an array-key can only be a numerical or string value (and not an array), I suppose you want to know about array-values ?
If so, you'll have to loop over your array, testing, for each element, if it's an array or not, keeping track of what's been found -- see the is_array function, about that.
Then, when you've tested all elements, you'll have to test if you found arrays, and/or non-array.
Something like this, I suppose, might do the trick :
$has_array = false;
$has_non_array = false;
foreach ($your_array as $element) {
if (is_array($element)) {
$has_array = true;
} else {
$has_non_array = true;
}
}
if ($has_array && $has_non_array) {
// both
} else {
if ($has_array) {
// only arrays
} else {
// only non-array
}
}
(Not tested, but the idea should be there)
This portion of code should work for the three first points you asked for.
To test for "array has no value", The fastest way is to use the empty() language construct before the loop -- and only do the loop if the array is not empty, to avoid any error.
You could also count the number of elements in the array, using the count() function, and test if it's equal to 0, BTW.
Some precalculation:
function isArray($reducedValue, $currentValue) {
// boolean value is converted to 0 or 1
return $reducedValue + is_array($currentValue);
}
$number_of_arrays = array_reduce($array, 'isArray', 0);
Then the different states can be evaluated as follows:
only arrays
count($array) == $number_of_arrays
only non-arrays
$number_of_arrays == 0
both array and non array keys
count($array) != $number_of_arrays
array has no keys
empty($array);
So you just need to write a function that returns the appropriate state.
Reference: in_array, array_reduce, empty
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.