php elegance keys unsetting - php

I need to remove from an array some keys.
$array = array('a' => 'a', 'b' => 'b', 'c' => 'c');
unset($array['a']);
unset($array['b']);
How can I do this more elegance? Maybe there is a function like this array_keys_unset('a', 'b')?I don't need array_values or foreach. I only want to know is it possible.
Thank you in advance. Sorry for my english and childlike question.

You can do that with single call to unset as:
unset($array['a'],$array['b']);

unset() is as simple as it gets, but as another solution how about this?
$keys_to_remove = array_flip(array('a', 'b'));
$array = array_diff_key($array, $keys_to_remove);
Put into a function:
function array_unset_keys(array $input, $keys) {
if (!is_array($keys))
$keys = array($keys => 0);
else
$keys = array_flip($keys);
return array_diff_key($input, $keys);
}
$array = array_unset_keys($array, array('a', 'b'));
Or you could even make it unset()-like by passing it a variable number of arguments, like this:
function array_unset_keys(array $input) {
if (func_num_args() == 1)
return $input;
$keys = array_flip(array_slice(func_get_args(), 1));
return array_diff_key($input, $keys);
}
$array = array_unset_keys($array, 'a', 'b');

Personally, I would just do this if I had a long / arbitrary list of keys to set:
foreach (array('a', 'b') as $key) unset($array[$key]);
You could use a combination of array functions like array_diff_key(), but I think the above is the easiest to remember.

What's wrong with unset()?
Note that you can do unset($array['a'], $array['b']);
You could also write a function like the one you suggested, but I'd use an array instead of variable parameters.

No, there is no predefined function like array_keys_unset.
You could either pass unset multiple variables:
unset($array['a'], $array['b']);
Or you write such a array_keys_unset yourself:
function array_keys_unset(array &$arr) {
foreach (array_slice(func_get_args(), 1) as $key) {
unset($arr[$key]);
}
}
The call of that function would then be similar to yours:
array_keys_unset($array, 'a', 'b');

Related

Check if one of multiple variables exists in array

$array = ['a', 'b', 'c', 'd'];
$vars = ['a', 'f', 'g'];
foreach ($vars as $var) {
if (in_array($var, $array)) {
return true;
} else {
return false;
}
}
How can i check if one of the $vars exists in $array? Only one of them needs to be true if all the others are false it is not a problem, But if there is more than 1 true value,
For example ['a', 'b', 'c', 'g'] i want the function to stop at the first true value and ends the process.
Simply with array_intersect function:
$arr = ['a', 'b', 'c', 'd'];
$vars = ['a', 'f', 'g'];
$result = count(array_intersect($vars, $arr)) == 1;
var_dump($result); // true
For me, the code you've got in the question is pretty much the best way to go about this. You just need to move the return false to after the loop, so that all values get processed:
foreach ($vars as $var) {
if (in_array($var, $array)) {
return true;
}
}
return false;
This will work identically to a solution with array_intersect, but has the advantage of only needing to process the minimum amount of the loop. Consider the following data:
$vars = [1, 2, 3, 4, ... 1,000,000,000];
$array = [1, 10, ...];
A solution using array_intersect will need check every element in $vars against every element in $array, whereas a solution that breaks out of a loop will only need to check until the first match. You could optimise this further by using two nested foreach loops if both your arrays are very large.
Like I mentioned in the comment - if your arrays are small then just use array_intersect, you won't notice any difference, and the code is a bit more readable.

In_array but with more values

Example:
$array = array('hi', 'hello', 'bye');
How can I check if at least one of two or more values are present in the array ?
like:
if(in_array('hi', $array) || in_array('hello', $array)) ...
but with a single check? can it be done?
if(count(array_intersect(array('hi','hello','bye'), $array))) {
...
}
function in_array2($ary1,$ary2){
return count(array_intersect($ary1,$ary2)) > 0;
}
Simple, make use of array_intersect.
Take a look at preg_grep, which will return entries in an array that match a predefined pattern (e.g. '/^(hi|hello)$/ in your example).
E.g.
if (count(preg_grep('^/(hi|hello)$/',$array)))
{
// your code
}
use array_intersect()... i.e.
$array = array('hi', 'hello', 'bye');
if(count(array_intersect($array, array('search', 'for', 'values')))>0) ....

array_walk or array_map?

I'm currently using array_map to apply callbacks to elements of an array. But I want to be able to pass an argument to the callback function like array_walk does.
I suppose I could just use array_walk, but I need the return value to be an array like if you use array_map, not TRUE or FALSE.
So is it possible to use array_map and pass an argument to the callback function? Or perhaps make the array_walk return an array instead of boolean?
You don't need it to return an array.
Instead of:
$newArray = array_function_you_are_looking_for($oldArray, $funcName);
It's:
$newArray = $oldArray;
array_walk($newArray, $funcName);
If you want return value is an array, just use array_map. To add additional parameters to array_map use "use", ex:
array_map(function($v) use ($tmp) { return $v * $tmp; }, $array);
or
array_map(function($v) use ($a, $b) { return $a * $b; }, $array);
Depending on what kind of arguments you need to pass, you could create a wrapped function:
$arr = array(2, 4, 6, 8);
function mapper($val, $constant) {
return $val * $constant;
}
$constant = 3;
function wrapper($val) {
return mapper($val, $GLOBALS['constant']);
}
$arr = array_map('wrapper', $arr);
This actually seems too simple to be true. I suspect we'll need more context to really be able to help.
To expand a bit on Hieu's great answer, you can also use the $key => $value pairs of the original array. Here's an example with some code borrowed from comment section http://php.net/manual/en/function.array-map.php
The following will use 'use' and include an additional parameter which is a new array.
Below code will grab "b_value" and "d_value" and put into a new array $new_arr
(useless example to show a point)
// original array
$arr = ("a" => "b_value",
"c" => "d_value");
// new array
$new_arr = array();
array_map(function($k,$v) use (&$new_arr) { $new_arr[] = $v;}, array_keys($arr), $arr);
^ $k is key and $v is value
print_r of $new_arr is
Array
(
[0] => b_value
[1] => d_value
)

Substract one array from another

Well, I have
$a2 = array('a'=>'Apple','b'=>'bat','c'=>'Cat','d'=>'Dog','e'=>'Eagle','f'=>'Fox','g'=>'God');
$a3 = array('b','e');
I want to substract $a3 from $a2 to get:
$aNew = array('a'=>'Apple','c'=>'Cat','d'=>'Dog','f'=>'Fox','g'=>'God');
Any help?
the are two built-in functions to do something similar: array_diff and array_diff_assoc - but both won't work in your case.
so, to do what you want, you'll have to change the markup of your $a3 a bit to fit these functions (take a look at the documentation), or you'll have to loop $a3 and delete the elements from $a2 manually like this:
foreach($a3 as $k){
unset($a2[$k]);
}
foreach($a3 as $value){
if(isset($a2[$value]))
unset($a2[$value]);
}
Don't get it.
$aNew = $a2;
foreach($a3 as $key) unset($aNew[$key]);
you need this one?
This can be done with php built-in functions.
Since the array $a2 contains the values of the keys you want to remove, you need first to create an array containing the values of $a2 as keys using array_flip. Then you can just use array_diff_key. So try this:
$aNew = array_diff_key($a2, array_flip($a3));
Note that you need php > 5.1.0 for this to work.
$aNew = array();
foreach (array_diff(array_keys($a2), $a3) : $key) {
$aNew[key] = $a2[key];
}
This sould do the job. Grap the keys from a2 remove all keys which exist in a3 and then copy the remaining keys to a new array. You could also remove the keys from the old array. This is up to you.
Edit: +$
The difficulty here lies in that you compare key of one array with values of another one. E.g. by the use of array_diff_ukey.
Excerpt from PHP manual:
function key_compare_func($key1, $key2)
{
if ($key1 == $key2)
return 0;
else if ($key1 > $key2)
return 1;
else
return -1;
}
$array1 = array('blue' => 1, 'red' => 2, 'green' => 3, 'purple' => 4);
$array2 = array('green' => 5, 'blue' => 6, 'yellow' => 7, 'cyan' => 8);
var_dump(array_diff_ukey($array1, $array2, 'key_compare_func'));
array(2) {
["red"]=>
int(2)
["purple"]=>
int(4)
}
Your second array is not associative, so this would compare "a" with 0, e.g.
So it's:
$compareFunc = function($key) uses ($a3) {
if(array_key_exists($key, $a3) {
return true;
}
else return false;
}
array_map($compareFunc, $a2);
can't be used neither, because this function is used to modify but not to reduce the array.
$a4 = array();
$compareFunc = function($key) uses ($a3, &$a4) {
if(array_key_exists($key, $a3) {
array_push($a4);
}
}
would do the job.
What I am trying to achieve is:
Play around with the PHP - functions that provide callbacks to you when the standart - functions don't succeed.
Try using the concept of binding, when the describtion of the callback doesn't fit your needs. With PHP's Lambda - functions you can bind objects / variables to a function,
so that you have access to variables that are not passed to the callback.
Get creative!!!
Try using array_diff
but you need to make some changes on your $a3.
$a3 = array('bat', 'Eagle');
//and then
$a4 = array_diff($a2, $3);
because without specifying a key (in key => value format), the string will automatically become a value instead.

If [Get Variable] is equal to [Array]

I am trying to find easier and simple way to code a logic.
That is if one variable is equal to any key values in an array.
For instance:
$someArray = array("a","b","c");
If($_GET["foobar"] == $someArray) {
return true;
} else {
return false;
}
If the $_GET["foobar"] had a value of A, B, or C, the case would return true. If it was any other values, it would return false.
Thanks for the help.
return in_array($_GET["foobar"], $someArray, true);
EDIT: Added optional true parameter.
Rather than integer-indexed arrays, you can make use of associative arrays:
$someArray = array('a' => 1, 'b' => 1, 'c' => 1);
if (isset($someArray[$_GET['foobar']])) {
...
}
If you don't like to type out all the array values or the values of $someArray need to stay as they are, you can use array_flip:
$someArray = array('a', 'b', 'c');
...
$otherArray = array_flip($someArray);
if (isset($otherArray[$_GET['foobar']])) {
...
}
You can even store useful information in the values of the associative array.
You can use the in_array() function. I'm pretty sure it's exactly what you are looking for. Here is the function in the code sample you provided.
$someArray = array("a","b","c");
if(in_array($_GET["foobar"],$someArray)) {
return true;
} else {
return false;
}

Categories