Unset inside array_walk_recursive not working - php

array_walk_recursive($arr, function(&$val, $key){
if($val == 'smth'){
unset($val); // <- not working, unset($key) doesn't either
$var = null; // <- setting it to null works
}
});
print_r($arr);
I don't want it to be null, I want the element out of the array completely. Is this even possible with array_walk_recursive?

You can't use array_walk_recursive here but you can write your own function. It's easy:
function array_unset_recursive(&$array, $remove) {
$remove = (array)$remove;
foreach ($array as $key => &$value) {
if (in_array($value, $remove)) {
unset($array[$key]);
} elseif (is_array($value)) {
array_unset_recursive($value, $remove);
}
}
}
And usage:
array_unset_recursive($arr, 'smth');
or remove several values:
array_unset_recursive($arr, ['smth', 51]);

unset($val) will only remove the local $val variable.
There is no (sane) way how you can remove an element from the array inside array_walk_recursive. You probably will have to write a custom recursive function to do so.

The answer of #dfsq is correct but this function doesn't remove empty array. So you can end up with Tree of empty array, which is not what is expected in most cases.
I used this modified function instead:
public function array_unset_recursive(&$array, $remove) {
foreach ($array as $key => &$value) {
if (is_array($value)) {
$arraySize = $this->array_unset_recursive($value, $remove);
if (!$arraySize) {
unset($array[$key]);
}
} else if (in_array($key, $remove, true)){
unset($array[$key]);
}
}
return count($array);
}

Related

how can I get my php array data to persist?

When I query the data within the foreach loop it works, but makes a duplicate for each pass in the loop. I try to var_dump it anywhere else outside the loop and the data isn't there. Why won't my data persist outside the forEach loop?
<?php
$old_array = [10-2, 13=>"3452", 4=>"Green",
5=>"Green", 6=>"Blue", "green"=>"green",
"two"=>"green" ,"2"=>"green" , "rulebreak" =>"GrEeN",
"ninja"=>" Green ", ["blue" => "green", "green"=>"green", 2 => "itsGreen"] ];
$newArray = array();
function filter_Green($array) {
$find = "green";
$replace = "not green";
/* Same result as using str_replace on an array, but does so recursively for multi-dimensional arrays */
/* found here:
if (!is_array($array)) {
/* Used ireplace so that searches can be case insensitive */
return str_ireplace($find, $replace, $array);
}
foreach ($array as $key => $value) {
$newArray[$key] = $value;
if ($key == "green") {
$newArray[$key] = "not green";
}
if ($value == "green") {
$newArray[$value] = "not green";
}
}
return $newArray;
}
filter_Green($old_array);
var_dump($newArray);
?>
Expectation: When I run the function it should replace all instances of "green" with "not green" and save those into a $newArray. I have it returning $newArray but even then it doesn't seem to match up that the values are being saved into the newArray, hence why I'm doing var_dump to check if it's even working (it appears to not be)
Results: as it is setup, I get an empty array returned to me...It seems to work somewhat if I move var_dump($newArray) to within the foreach loop but that then duplicates the data for each pass.
if you want var_dump $newArray out side the function then you should declare $newArray as global in your function
<?php
$old_array = [10-2, 13=>"3452", 4=>"Green", 5=>"Green", 6=>"Blue", "green"=>"green", "two"=>"green" ,"2"=>"green" , "rulebreak" =>"GrEeN", "ninja"=>" Green ", ["blue" => "green", "green"=>"green", 2 => "itsGreen"] ];
$newArray = array();
function filter_Green($array) {
global $newArray;
$find = "green";
$replace = "not green";
/* Same result as using str_replace on an array, but does so recursively for multi-dimensional arrays */
if (!is_array($array)) {
/* Used ireplace so that searches can be case insensitive */
return str_ireplace($find, $replace, $array);
}
foreach ($array as $key => $value) {
$newArray[$key] = $value;
if ($key == "green") {
$newArray[$key] = "not green";
}
if ($value == "green") {
$newArray[$value] = "not green";
}
}
return $newArray;
}
filter_Green($old_array);
var_dump($newArray);
?>
But instead of declaring global in function, use returned value by filter_Green($old_array); as below
$result = filter_Green($old_array);
var_dump($result);

Why "return" on PHP function is not stopping the process?

I do not understand why "return" is not stopping the process in this function that I created to search a value on a multi_level array in PHP.
This is the code:
static function in_array_multi($needle, $haystack) {
foreach ($haystack as $item) {
if(is_array($item)){
in_array_multi($needle, $item);
}
else{
if ($item === $needle) {
return "ok";
}
}
}
return "nok";
}
I am using this array as exemple:
$arr = array(0 => array(id=>1,name=>"cat 1"),
1 => array(id=>2,name=>"cat 2"),
2 => array(id=>3,name=>array(id=>7,name=>"cat 7"))
);
And I am calling the function like this:
echo in_array_multi("cat 1",$arr);
It is returning "nok".
I am using xdebug to follow the process. It should stop the process on the second round.
Someone has any idea about what is happening?
Thanks
My comment was a bit careless. You would only want to return directly from the recursion if the recursion actually finds the value. You could do
function in_array_multi($needle, $haystack) {
foreach ($haystack as $item) {
if(is_array($item)){
if ('ok' === in_array_multi($needle, $item)) {
return 'ok';
}
}
elseif ($item === $needle) {
return "ok";
}
}
return "nok";
}
Because you make the return of function will stop the loop, you should collect it and return in the final.
Maybe you want this..
function array_multiple_search($array, $key, $value=null) {
$return = array();
if (is_array($array)) {
if (isset($array[$key])) {
if (is_null($value)) {
$return[] = $array;
} elseif ($array[$key] == $value) {
$return[] = $array;
}
}
foreach ($array as $subarray) {
$return = array_merge($return, array_multiple_search($subarray, $key, $value));
}
}
return $return;
}
param 1 is the target array
param 2 is the key you want to search of target array
param 3 is the value you want to search with the key of target array(can null)
This function will collect and return an array of qualified.

Merge and sum two associatve arrays in PHP

Given these two arrays:
$first=array(
'books'=>1,
'videos'=>5,
'tapes'=>7,
);
$second=array(
'books'=>3,
'videos'=>2,
'radios'=>4,
'rc cars'=>3,
);
I would like to combine them so that I end up with
$third=array(
'books'=>4,
'videos'=>7,
'tapes'=>7,
'radios'=>4,
'rc cars'=>3,
);
I saw a function here: How to sum values of the array of the same key? but it looses the Key.
You can use something along the lines of:
function sum_associatve($arrays){
$sum = array();
foreach ($arrays as $array) {
foreach ($array as $key => $value) {
if (isset($sum[$key])) {
$sum[$key] += $value;
} else {
$sum[$key] = $value;
}
}
}
return $sum;
}
$third=sum_associatve(array($first,$second));
Just to be different... Uses func_get_args(), closures and enforces arguments to be arrays:
function sum_associative()
{
$data = array();
array_walk($args = func_get_args(), function (array $arg) use (&$data) {
array_walk($arg, function ($value, $key) use (&$data) {
if (isset($data[$key])) {
$data[$key] += $value;
} else {
$data[$key] = $value;
}
});
});
return $data;
}

why I cannot unset the value of an array(PHP)

I want to unset a field of a two-dimensional array. I got a function like this, but it doesn't work:
function excludeOldScreeningDate($array){
foreach($array as $val){
if($val['ref'] == 'G'){
unset($val['screening_date']);
}
}
return $array;
}
Because you're unsetting only temporary variable $val
function excludeOldScreeningDate($array){
foreach($array as $index => $val){
if($val['ref'] == 'G'){
unset($array[$index]['screening_date']);
}
}
return $array;
You should pass elements of an array by reference:
function excludeOldScreeningDate($array){
foreach($array as &$val){
if($val['ref'] == 'G'){
unset($val['screening_date']);
}
}
return $array;
}
Notice the foreach($array as &$val){ line has changed.
If you want to edit the values in the array, you can read each array element by reference. Put a & in front of $val in the foreach.
function excludeOldScreeningDate($array){
foreach($array as &$val){
if($val['ref'] == 'G'){
unset($val['screening_date']);
}
}
return $array;
}

access php array children through parameters?

I have a unique case where I have an array like so:
$a = array('a' => array('b' => array('c' => 'woohoo!')));
I want to access values of the array in a manner like this:
some_function($a, array('a')) which would return the array for position a
some_function($a, array('a', 'b', 'c')) which would return the word 'woohoo'
So basically, it drills down in the array using the passed in variables in the second param and checks for the existence of that key in the result. Any ideas on some native php functions that can help do this? I'm assuming it'll need to make use of recursion. Any thoughts would be really appreciated.
Thanks.
This is untested but you shouldn't need recursion to handle this case:
function getValueByKey($array, $key) {
foreach ($key as $val) {
if (!empty($array[$val])) {
$array = $array[$val];
} else return false;
}
return $array;
}
You could try with RecursiveArrayIterator
Here is an example on how to use it.
Here’s a recursive implementation:
function some_function($array, $path) {
if (!count($path)) {
return;
}
$key = array_shift($path);
if (!array_key_exists($key, $array)) {
return;
}
if (count($path) > 1) {
return some_function($array[$key], $path);
} else {
return $array[$key];
}
}
And an iterative implementation:
function some_function($array, $path) {
if (!count($path)) {
return;
}
$tmp = &$array;
foreach ($path as $key) {
if (!array_key_exists($key, $tmp)) {
return;
}
$tmp = &$tmp[$key];
}
return $tmp;
}
These functions will return null if the path is not valid.
$a['a'] returns the array at position a.
$a['a']['b']['c'] returns woohoo.
Won't this do?

Categories