I recently had to write a piece of code where I used the following; but it was very confusing for me and took me longer than I should
I keep getting lost by the negation and false turning into true and then back maybe. I end up solving these problems by trial and error.
Here is the code for getting rid of empty elements. NB, perhaps there are better code but I'm interested in knowing how to think this through
array_filter($array, "eliminate");
function eliminate($v)
{
return !(empty($v));
}
array_filter takes two arguments. The first is an array. The second is a callback. Here you are using the name of a function contained within a string "eliminate" to tell PHP which function you want to invoke.
The purpose of array_filter is to remove items from the array if you don't want them. The function from the second argument is called on every item in the array. The item is passed as the first argument to that function -- so $v in your above code is set to the value of the element we're looking at. If you return true from your callback, the item is kept in the array. If you return false, it is removed.
Your function returns true or false based on the following:
return !(empty($v));
empty returns true if the element is empty (e.g. an empty string, an empty array, the integer 0, among others). The ! operator turns this around. So the function will return false (and remove the item from the array) if the item is empty. Otherwise, it will return true and keep it.
Your function is approximately equivalent to the following loop:
$newArray = array();
foreach ($oldArray as $key=>$value) {
if (!empty($value)) {
$newArray[$key] = $value;
}
}
Iterates over each value in the input array passing them to the callback function. If the
callback function returns true, the current value from input is returned into the result array.
Array keys are preserved.
Source: http://php.net/array_filter
Each element is passed to eliminate function. Now inside eliminate if the value passed is empty it will return false and it will not belong in the next array.
Please note that your code does nothing because you should do:
$newArray=array_filter($array, "eliminate"); //< note the newarray
function eliminate($v)
{
return !(empty($v));
}
Or a better code with PHP 5.3
$newArray=array_filter($array, function ($v){
return !(empty($v));
} );
The best way to think about this code is by "talking" it out:
Let's start with eliminate, eliminate returns true when $v is not empty, false otherwise
Now, array_filter applies the designated function, here it's eliminate, to every element in $array, one at a time.
Finally, we need to understand that if, for some single element $v in $array, eliminate($v) returns true, then that element is removed.
array_filter runs the callback function on each array element. If the callback returns true, the element is kept, if false it's removed.
So, for every element in $array, it checks if it's empty(). If it's not, it gets to stay in the array, if it is it leaves. empty() returns true if it's empty (which means we want it removed from the array), so we need to return false.
If you call array_filter without a callback, it remove things that convert to false, so in your case $array = array_filter($array); should work.
array_filter returns you the modified array.
Just use:
array_filter($array);
This will eliminate every empty element of the array - the result should be identical to the code you have shown (with 'eliminate' function and !(empty($v)) code).
Related
I noticed the following strange occurrence:
var_dump(in_array("test", array_keys(array("hello"))));
Yields: bool(true)
How is this possible? Array does not contains keys, therefore array_keys() will return an empty array. Test is not in this empty array, so why would it return true? Is this a bug in PHP?
simple answer: loose typing, 'test' == 0
Use
var_dump(in_array("test", array_keys(array("hello")), true));
for strict typing
And all arrays have keys, if you don't explicitly assign a key, then PHP will assign one based on incrementing integers from 0 (hence 'test' == 0).... array_keys() will not be empty, because PHP will assign a key of 0 to your array entry of "hello"
In my code, I fill an array using this line in a loop :
$_SESSION['my_array'][] = $some_value;
After each execution of this line, I do some check (doesn't matter here for which purpose) using the function in_array(). However, at the first iteration it says :
« in_array() expects parameter 2 to be array ».
How to fix this problem?
You can initialize the array (before you fill it with values) like this:
$_SESSION['my_array']=array();
This way you can be sure that it is array, even when it would be empty.
You are assigning or accesing it wrongly
Use this
$_SESSION['my_array'] = $some_value;
When you are doing the in_array check, you can cast the second item to an array, so if it's empty then it will pass an empty array. This way you don't ever set anything to the session when you don't need to (which could trip you up later on)
e.g.,
if (in_array('foo', (array)$_SESSION['my_array'])) {
// do something
}
What I started with:
foreach($a as $b){if($b=='')return 0;}return 1; // works but verbose
My second attempt:
return (in_array('',$a)+0); // returns the opposite of what I need
What I am currently using:
return in_array('',$a)?'0':'1';
using a cast per JRL (shortest)
return (int)!in_array('',$a);
I assume this is the best way to do this, but just wanted to validate. Is this the best way to test for an empty value in an array?
I am aware that this tests for 0,NULL,FALSE or an empty string and that is O.K.
Here's a modification of your second statement that should work. Just negate the return value of in_array:
return !in_array('',$a);
Other alternative:
return (int)!in_array('', $a));
Your proposal to check an array $a for strings cannot be written shorter than:
return in_array('', $a)?0:1;
If you want to see the difference between 0, NULL, FALSE, or an empty string, add a third parameter to the in_array function. This parameter will force the function to also take the type of the element into account. In other words, it compares using === instead of ==.
return in_array('', $a, TRUE)?0:1; //Empty string
return in_array(0, $a, TRUE)?0:1; //Zero
return in_array(NULL, $a, TRUE)?0:1; //NULL
return in_array(FALSE, $a, TRUE)?0:1;//FALSE
See also: http://www.php.net/manual/en/function.in-array.php
First one isn't correct.
Second one isn't correct
Third one is perfect for your case
OT: Trying to codegolf?
I think as far as best practice goes, just plain !in_array('', $a) is the way to go.
There's (generally speaking) no good reason to cast it to an int. Type juggling in PHP works very well. It isn't the PHP way to do casts like this.
Could some one explain me this while loop?
while (list($key, $value) = each($HTTP_GET_VARS)) {
$get_url .= $key . '=' . $value . '&';
}
I know its silly but many times silly things makes huge difference....
$HTTP_GET_VARS is a deprecated array that contains the parameters passed in the querystring. each() is a function that iterates through an array and returns an array consisting of the key and value of the "current" element of the array. list() is a language construct that explodes an array assigned to it into the variables passed to it.
When the end of the array is reached, each() returns a false value, causing the loop to exit.
The each() function returns the current key and value for the given array, and then moves the array pointer (the current item) forward by one.
Therefore, calling it multiple times is a way to iterate through the items in the array in order, and when you reach the end, each() just stops returning a value.
The list() is not a function but a language construct; it's a shortcut for setting multiple variables at once. In the example posted it sets $key to the first value in the array returned by each() (the current key) and $value to the second (the current value).
There's a number of problems with that code snippet.
You should reset the array pointer before you use each() like this, because you shouldn't assume that the array pointer is at the start by the time this code executes.
The values it is concatenating into a query string should be escaped (eg. by urlencode()).
It's also leaving a separating '&' character at the end of the query string unnecessarily.
$HTTP_GET_VARS is a deprecated feature of PHP; it should be replaced with $_GET.
Iterating over an array with foreach () is cleaner and easier to read than while, list, each like this, and may be faster too.
each returns an array containing the current key and value, as you iterate through an array. list lets you unpack an array into multiple variables. I find the foreach construct much more clear.
foreach ($some_array as $key => $value)
{
...
}
As noted by Ignacio, HTTP_GET_VARS is deprecated. You can use $_GET instead.
The loop goes through each of the pairs of HTTP GET parameters in the array $HTTP_GET_VARS, assigning the sides of the pair to two variables $key and $value in that order.
The assignment 'returns' its value, hence, at the end of the array, each() will return false, which despite the assignment will cause the while condition to abort.
Inside the loop, each of $key and $value are appended to the string $get_url with some formatting.
I know there is array_key_exists() but after reading the documentation I'm not really sure if it fits for this case:
I have an $array and an $index. Now I want to access the $array, but don't know if it has an index matching $index. I'm not talking about an associative array, but an plain boring normal numerically indexed array.
Is there an safe way to figure out if I would really access an $array element with the given $index (which is an integer!)?
PHP may not care if I access an array with an index out of bounds and maybe just returns NULL or so, but I don't want to even attempt to code dirty, so I want to check if the array has the key, or not ;-)
You can use either the language construct isset, or the function array_key_exists : numeric or string key doesn't matter : it's still an associative array, for PHP.
isset should be a bit faster (as it's not a function), but will return false if the element exists and has the value NULL.
For example, considering this array :
$a = array(
123 => 'glop',
456 => null,
);
And those three tests, relying on isset :
var_dump(isset($a[123]));
var_dump(isset($a[456]));
var_dump(isset($a[789]));
You'll get this kind of output :
boolean true
boolean false
boolean false
Because :
in the first case, the element exists, and is not null
in the second, the element exists, but is null
and, in the third, the element doesn't exist
On the other hand, using array_key_exists like in this portion of code :
var_dump(array_key_exists(123, $a));
var_dump(array_key_exists(456, $a));
var_dump(array_key_exists(789, $a));
You'll get this output :
boolean true
boolean true
boolean false
Because :
in the two first cases, the element exists -- even if it's null in the second case
and, in the third, it doesn't exist.
You can easily use isset():
if (isset($array[$index])) {
// array index $index exists
}
And as you have suggested, PHP is not very kind if you try to access a non-existent index, so it is crucial that you check that you are within bounds when dealing with accessing specific array indexes.
If you decide to use array_key_exists(), please note that there is a subtle difference:
isset() does not return TRUE for array
keys that correspond to a NULL value,
while array_key_exists() does.
That's exactly what the array_key_exists is for. It works on both numerical and string indexes.