I have a simple way to detect references in an array (For debugging purposes)
First I clone the array with array_values and then I alter the clone and look for changes in the original. If it's changed that element is a reference.
Short example:
<?php
$a = [
'a' => 'b',
2 => 3,
];
$b = ['wow'];
$a['ref'] = &$b;
function getrefs($array) {
$marker = uniqid();
$copy = array_values($array);
$i = 0;
$return = [];
foreach ($array as $key => &$val) {
$stash = $val;
$copy[$i] = $marker;
if ($val === $marker) {
$val = $stash;
$return[] = $key;
}
$i++;
}
return $return;
}
var_dump($a);
var_dump(getrefs($a));
The problem is that when I try to use this on $GLOBALS it's not working, and I can't figure out why. Everything in $GLOBALS should be a reference by all rights.
Is $GLOBALS just so strange that it's the only array where array_values won't correctly copy references?
It's a possibility that you're not accounting for recursion. The built-in PHP function:
var_dump($GLOBALS);
Will have the following output
array(7) {
["_GET"]=>
array(0) {
}
["_POST"]=>
array(0) {
}
["_COOKIE"]=>
array(1) {
["PHPSESSID"]=>
string(26) "od602et6qcfj6pa3pkjtl8go57"
}
["_FILES"]=>
array(0) {
}
["GLOBALS"]=>
*RECURSION*
["_SESSION"]=>
&array(0) {
}
}
Related
i have string like this
$string = 'root.1.child1.2.nextnode.3.anothernode.4.var';
exploded by "." and created array like this
$arr = array('root','1','child1','2','nextnode','3','anothernode','3','var');
how i can convert this array to something like this ?
it should be dynamically convert because in some cases nodes in string are in a number different with the sample .
["root"]=>
array(1) {
[1]=>
array(1) {
["child1"]=>
array(1) {
[2]=>
array(1) {
["nextnode"]=>
array(1) {
[3]=>
array(1) {
["anothernode"]=>
array(1) {
[3]=>
array(1) {
[var]=>
NULL
}
}
}
}
}
}
}
}
An example using recursive function.
$array = ['root', '1', 'child1', '2', 'nextnode', '3', 'anothernode', '3', 'var'];
function getNestedArray(array $arr, int $idx = 0) {
if ($idx + 1 <= count($arr)) {
return [$arr[$idx] => getNestedArray($arr, $idx + 1)];
}
return null;
}
$output = getNestedArray($array);
var_dump($output);
This can be quit easily achieved by referencing the output and looping over the exploded array:
$output = [];
$reference = &$output;
foreach ($arr as $el) {
if (is_numeric($el)) {
$el = (int)$el;
}
$reference = [];
$reference[$el] = null;
$reference = &$reference[$el];
}
This also checks whether the element is a number and casts it to an integer if it is. The $output variable will contain the final array.
You can use recursive function
to do though
$flatArray = array('root','1','child1','2','nextnode','3','anothernode','3','var'); // your array
function createNestedArray($flatArray)
{
if( sizeof($flatArray) == 1 ) {
return [ $flatArray[0] => null ]; // for the case that paramter has one member we need to return [ somename => null ]
}
$nestedArray[ $flatArray[0] ] = createNestedArray(array_slice($flatArray, 1)); // otherwise we need to call createNestedArray with rest of array
return $nestedArray;
}
$nestedArray = createNestedArray($flatArray); // the result
Is it possible to search an array for a given value and return all the indexes at which the value was found? So for this array:
["Red","Green","Red","Blue"]
I need
[0,2]
with regard to a search for "Red". Searching for "Yellow" in this case would return an empty array.
You can use like this:
$array = ["Red","Green","Red","Blue"];
$output = array_keys($array, "Red");
The $output will be [0,2]
I think this should work:
$input = ["Red","Green","Red","Blue"];
$x = "Red";
$keys = array_keys(array_filter($input, function ($v) use ($x) { return $v === $x;}));
You can iterate the array with foreach:
foreach($input_arr as $key => $value){
if($value == 'Red'){
needed_key_arr[] = $key;
}
}
Also, if you can have an array of values you what to search use:
$lookup_arr = ['Red', 'Green'];
foreach($input_arr as $key => $value){
if(in_array($value, $lookup_arr)){
needed_key_arr[] = $key;
}
}
$arr = ["Red","Green","Red","Blue"];
$valueToSearchFor = ["Red"];
$keys = array_keys(array_filter($arr, function ($val1) use ($valueToSearchFor) { // filter the first array
return array_filter($valueToSearchFor, function ($val) use ($val1) { // use the first array's value
return $val == $val1; // compare them and then return them
});
}));
var_dump($keys) // array(2) { [0]=> int(0) [1]=> int(2) }
First we filter the array then take the values from the first filter to another filter then we match the arrays and we return them. This works for multiple values too.
$arr = ["Red","Green","Red","Blue"];
$valueToSearchFor = ["Red", "Blue"];
$keys = array_keys(array_filter($arr, function ($val1) use ($valueToSearchFor) {
return array_filter($valueToSearchFor, function ($val) use ($val1) {
return $val == $val1;
});
}));
var_dump($keys) // array(3) { [0]=> int(0) [1]=> int(2) [2]=> int(3) }
I have an associative array in php. When I am doing a die on it, then I am getting proper values as follows:
array(1) { [0]=> array(1) { [123]=> string(5) "Hello" }}
But when I am trying extract out keys of this array into an new array, then I am not able to get keys out:
$uniqueIds = array_keys($myAssociativeArray);
die(var_dump($uniqueIds));
int(0) array(1) { [0]=> int(0) }
Can any one tell me what I am doing wrong here? I want to get all the keys out of my associative array. And for this, I am referring to thread: php: how to get associative array key from numeric index?
$uniqueIds = array_keys($myAssociativeArray[0]);
<?php
function multiarray_keys($ar) {
foreach($ar as $k => $v) {
$keys[] = $k;
if (is_array($ar[$k]))
$keys = array_merge($keys, multiarray_keys($ar[$k]));
}
return $keys;
}
$result = multiarray_keys($myAssociativeArray);
var_dump($result);
?>
The following recursively gets all the keys in an associative array
function getArrayKeysFlat($array) {
if(!isset($keys) || !is_array($keys)) {
$keys = array();
}
foreach($array as $key => $value) {
$keys[] = $key;
if(is_array($value)) {
$keys = array_merge($keys,getArrayKeysFlat($value));
}
}
return $keys;
}
I have an array similar to this:
array(2) {
[0]=>
array(2) {
["code"]=>
string(2) "en"
["name"]=>
string(7) "English"
}
[1]=>
array(2) {
["code"]=>
string(2) "bg"
["name"]=>
string(9) "Bulgarian"
}
}
How do I check if the string Bulgarian is part of the above array, or alternatively if the lang code 'en' is part of the array? It would be great if I didn't have to use foreach to loop through the entire array and compare the string with each element['code'] or element['name'].
// $type could be code or name
function check_in_array($arr, $value, $type = "code") {
return count(array_filter($arr, function($var) use ($type, $value) {
return $var[$type] === $value;
})) !== 0;
}
I know my code used foreach but it is easy to understand and use.
$language=array();
$language[0]['code']='en';
$language[0]['name']='English';
$language[1]['code']='bg';
$language[1]['name']='Bulgaria';
var_dump(my_in_array('Bulgaria', $language));
function my_in_array($search, $array) {
$in_keys = array();
foreach($array as $key => $value){
if(in_array($search, $value)){
$in_keys[]=$key;
}
}
if(count($in_keys) > 0){
return $in_keys;
}else{
return false;
}
}
You can use this function for recursive search
function in_arrayr($needle, $haystack) {
foreach ($haystack as $v) {
if ($needle == $v) return true;
elseif (is_array($v)) return in_array($needle, $v);
}
return false;
}
Or you can use json_encode on your array and search occurence of substring :)
I had a similar problem, so I made this function, it's like in_array, but it can search in array in the array recursively. I think it's correct but I didn't test in a lot of case. (sorry for my english I'm french)
function in_arrayr($needle, $haystack) {
if(is_array($haystack)){
foreach($haystack as $elem){
$a = in_arrayr($needle,$elem)||$a;
}
}
else{
$a = (($needle == $haystack)? true: false);
}
return $a;
}
I have been having issues with an array being modified when passed by value to a function.
I have inspected the code and inside the function the array is looped getting the elements by reference.
I was surprised to see that after the loop the array items are marked as referenced. I don't know what this means, but must be the origin of my problem.
Let me put an example to see the point.
<?php
error_reporting(E_ALL);
ini_set('display_errors' , 1);
$a = array( array(0) );
echo '--1--';var_dump($a);
dummy($a);
echo '--4--';var_dump($a);
function dummy($arg) {
foreach($arg as &$item) {
$item[0] = 3;
}
dummy2($arg);
echo '--3--';var_dump($arg);
}
function dummy2($arg) {
foreach($arg as &$item) {
$item[1]=9;
}
echo '--2--';var_dump($arg);
}
?>
After this code I would expect that in point 3, $arg would have only one element, but it has two, so it has been modified by dummy2 function.
The output is as follows:
--1--array(1) { [0]=> array(1) { [0]=> int(0) } }
--2--array(1) { [0]=> &array(2) { [0]=> int(3) [1]=> int(9) } }
--3--array(1) { [0]=> &array(2) { [0]=> int(3) [1]=> int(9) } }
--4--array(1) { [0]=> array(1) { [0]=> int(0) } }
Why are the arrays marked as &array after being looped by reference?
How can this be avoid?
You need to unset the loop variable that captures by reference:
<?php
error_reporting(E_ALL);
ini_set('display_errors' , 1);
$a = array( array(0) );
echo '--1--';var_dump($a);
dummy($a);
echo '--4--';var_dump($a);
function dummy($arg) {
foreach($arg as &$item) {
$item[0] = 3;
}
unset($item);
dummy2($arg);
echo '--3--';var_dump($arg);
}
function dummy2($arg) {
foreach($arg as &$item) {
$item[1]=9;
}
unset($item);
echo '--2--';var_dump($arg);
}
?>
See in the documentation for foreach, there is a big red warning that says:
Reference of a $value and the last array element remain even after the
foreach loop. It is recommended to destroy it by unset().
Use key => value pairs and return the array in your functions
<?php
error_reporting(E_ALL);
ini_set('display_errors' , 1);
$a = array( array(0) );
echo '--1--';var_dump($a);
$a = dummy($a);
echo '--4--';var_dump($a);
function dummy($arg) {
foreach($arg as $key => $value) {
$arg[$key][0] = 3;
}
return dummy2($arg);
}
function dummy2($arg) {
foreach($arg as $key => $value) {
$arg[$key][1]=9;
}
return $arg;
}
?>
http://codepad.org/f30c6FUj