how to get the index of a children array for an array look like this:
Array
(
[1000] => Array
(
[firstName] => Ori
[lastName] => Smith
[children] => Array
(
[0] => 1001
[1] => 1002
[2] => 1003
[3] => 1004
[4] => 1005
[5] => 1006
[6] => 1007
[7] => 1008
[8] => 1009
[9] => 1010
)
)
)
so if I give 1009 as the search, it should return 1000.
It does not work with this code:
array_search($childrenId, array_column(myArray, 'children'));
Try this
$result = array(
'1000'=>array('children'=>array('1001','1002')),
'2000'=>array('children'=>array('2001','2002'))
);
$searchValue = 2001;
$keyName = '';
foreach ($result as $key => $row) {
foreach ($row['children'] as $child) {
if ($child == $searchValue) {
$keyName = $key;
break;
}
}
}
echo $keyName;
You can use this function found here:
function getParentStack($child, $stack) {
foreach ($stack as $k => $v) {
if (is_array($v)) {
// If the current element of the array is an array, recurse it and capture the return
$return = getParentStack($child, $v);
// If the return is an array, stack it and return it
if (is_array($return)) {
return array($k => $return);
}
} else {
// Since we are not on an array, compare directly
if ($v == $child) {
// And if we match, stack it and return it
return array($k => $child);
}
}
}
// Return false since there was nothing found
return false;
}
I guess you could get the key by key(getParentStack(1009, $myarr)) or modify the function.
Related
I have a bunch of name-parentname pairs, that I turned into a heirarchical tree structure. So for example, these are my pairings:
Child : Parent
H : G
F : G
G : D
E : D
A : E
B : C
C : E
D : 0
Which after using this function found here.
$array = array('H' => 'G', 'F' => 'G', ..., 'D' => null);
function to_tree($array)
{
$flat = array();
$tree = array();
foreach ($array as $child => $parent) {
if (!isset($flat[$child])) {
$flat[$child] = array();
}
if (!empty($parent)) {
$flat[$parent][$child] =& $flat[$child];
} else {
$tree[$child] =& $flat[$child];
}
}
return $tree;
}
$array_tree = to_tree($array)
I get an array like this:
Array
(
[7] => Array
(
[24] => Array
(
)
[38] => Array
(
)
[78] => Array
(
)
[103] => Array
(
)
[121] => Array
(
)
[163] => Array
(
[162] => Array
(
)
[213] => Array
(
)
[214] => Array
(
)
[215] => Array
(
)
)
...
What I need is to get an array of the key i'm looking for plus all the children keys.
Let's say I'm looking for key 7, so I would get an array like this one:
Array
(
[0] => 7
[1] => 24
[2] => 38
[3] => 78
[4] => 103
[5] => 121
[6] => 163
[7] => 162
[8] => 213
[9] => 214
[10] => 215
...
)
But I also need to look on keys like 163 and get:
Array
(
[0] => 163
[1] => 162
[2] => 213
[3] => 214
[4] => 215
)
I think is not that hard for experienced users, but I can't quite figure it out.
<?php
$data = array(
'H' => 'G',
'F' => 'G',
'G' => 'D',
'E' => 'D',
'A' => 'E',
'B' => 'C',
'C' => 'E',
'D' => '0'
);
$root_node = 'G'; // Change the root node here.
$parents_with_children = array();
// 1) First create a data structure with parents and children.
foreach($data as $child => $parent){
if(!isset($parents_with_children[$parent])){
$parents_with_children[$parent] = array();
}
$parents_with_children[$parent][] = $child;
}
// 2) Then call a recursive function to find the tree structure, from a specific root node
find_children($root_node, $parents_with_children);
function find_children($root_node, $parents_with_children){
echo '<br>Parent:'.$root_node;
$found_children = array();
foreach($parents_with_children as $parent => $children){
if($parent === $root_node){
foreach($children as $child){
if(!in_array($child, $found_children)){
echo '<br>- Child:'.$child;
$found_children[] = $child;
}
}
}
}
foreach($found_children as $child){
find_children($child, $parents_with_children);
}
} // find_children
?>
After digging a lot I came up with this solution:
function get_children($needle, array $haystack, array &$result = null, $found = false) {
// This is to initialize the result array and is only needed for
// the first call of this function
if (is_null($result)) {
$result = [];
}
foreach ($haystack as $key => $value) {
// Check whether the key is the value we are looking for. If the value
// is not an array, add it to the result array.
if ($key === $needle && empty($value)) {
//key found but has no children, so lets add the key to the result.
$result[] = $key;
}
elseif ($key === $needle && !empty($value)) {
// key found and it has children so let's find all the children.
$result[] = $key;
get_children(null, $value, $result, true);
}
elseif ($found && empty($value)) {
// If key found then we add the children.
$result[] = $key;
}
elseif ($found && !empty($value)) {
// If key found but children has more children then were looking for them.
$result[] = $key;
get_children(null, $value, $result, true);
}
elseif (!empty($value)) {
// If we haven't found the key, we keep looking through subarrays.
get_children($needle, $value, $result, false);
}
}
return $result;
}
This is working great, I don't know if it's the best solution.
This question already has answers here:
How to use return inside a recursive function in PHP
(4 answers)
Closed 9 months ago.
I was working on an API for ustream which returns the following array
Array
(
[results] => Array
(
[0] => Array
(
[id] => 33756327
[userName] => sachintaware
[title] => Mobile record
[protected] =>
[description] => Recorded on my Android phone.
[createdAt] => 2013-06-03 03:29:38
[rating] => 0.000
[lengthInSecond] => 371.544
[totalViews] => 5
[codecIsForLiveHttp] =>
[url] => http://www.ustream.tv/recorded/33756327
[embedTag] =>
[liveHttpUrl] =>
[imageUrl] => Array
(
[small] => http://static-cdn2.ustream.tv/videopic/0/1/33/33756/33756327/1_14659377_33756327_120x90_b_1:2.jpg
[medium] => http://static-cdn2.ustream.tv/videopic/0/1/33/33756/33756327/1_14659377_33756327_320x240_b_1:2.jpg
)
[sourceChannel] => Array
(
[id] => 14659377
[url] => http://www.ustream.tv/channel/14659377
)
)
[1] => Array
(
[id] => 33756481
[userName] => sachintaware
[title] => gobiggitest
[protected] =>
[description] => gobiggitest
[createdAt] => 2013-06-03 03:37:49
[rating] => 0.000
[lengthInSecond] => 647.580
[totalViews] => 11
[codecIsForLiveHttp] =>
[url] => http://www.ustream.tv/recorded/33756481
[embedTag] =>
[liveHttpUrl] =>
[imageUrl] => Array
(
[small] => http://static-cdn2.ustream.tv/videopic/0/1/33/33756/33756481/1_14659377_33756481_120x90_b_1:3.jpg
[medium] => http://static-cdn2.ustream.tv/videopic/0/1/33/33756/33756481/1_14659377_33756481_320x240_b_1:3.jpg
)
[sourceChannel] => Array
(
[id] => 14659377
[url] => http://www.ustream.tv/channel/14659377
)
)
This is the function I used to go through the array as I want to fetch the [id] => 14659377 which is inside sourceChannel.But I am getting an empty value as a return value.What is the mistake I am making? can anyone please help me with it?
$getUsername = array();
function recursion($array) {
foreach ($array as $key => $value) {
if($key==='sourceChannel'){
$getId = $value['id'];
//print_r($getId);
return $getId;
}
if (is_array($value))
recursion($value);
}
}
$getUsername=recursion($resultsArray);
print_r($getUsername);
Your code is flawed because you need to change
recursion($value);
into
return recursion($value);
The return will take the answer back to the caller until the first caller is reached.
edit:
The lesson here is that your function should ALWAYS return a value. So here is some more elaboration:
function recursion($array) {
if (!is_array($array)) // check if what you're getting is an array!
return null;
foreach ($array as $key => $value) {
if($key==='sourceChannel') {
return $value['id'];
}
if (is_array($value)) {
$result = recursion($value);
if ($result !== null) {
return $result;
}
}
}
return null; // this happens if all recursions are done and sourceChannel was not found
}
You're not doing anything with the return from your recursion call.
It's a bit more complex than simply returning it, because you only want to cascade out if we actually found anything.
Try this:
function recursion($array) {
foreach ($array as $key => $value) {
if($key==='sourceChannel') {
return $value['id'];
}
if (is_array($value)) {
$rc = recursion($value);
if (!is_null($rc)) return $rc;
}
}
return null;
}
First, I added return null; to the end of the function - if we didn't find anything, we return null.
Then, when I recurse, I check the return value... if it's non-null, it means we found something and we want to return it. If it is null, we don't want to return - we want to continue the loop instead.
Try like this
foreach ($array['results'] as $key => $value) {
if($key == "sourceChannel"){
$getId = $value['id'];
//print_r($getId);
return $getId;
}
}
You could use iterators to make your function a whole lot easier:
function findSourceChannel($array)
{
foreach (new RecursiveIteratorIterator(new RecursiveArrayIterator($array)) as $key => $value) {
if ($key == 'sourceChannel') {
return $value['id'];
}
}
return null;
}
That said, I'm not sure why you can't just do a search like this:
foreach ($array['results'] as $result) {
if (isset($result['sourceChannel'])) {
return $result['sourceChannel']['id'];
}
}
return null;
This question already has answers here:
How to use return inside a recursive function in PHP
(4 answers)
Closed 9 months ago.
I was working on an API for ustream which returns the following array
Array
(
[results] => Array
(
[0] => Array
(
[id] => 33756327
[userName] => sachintaware
[title] => Mobile record
[protected] =>
[description] => Recorded on my Android phone.
[createdAt] => 2013-06-03 03:29:38
[rating] => 0.000
[lengthInSecond] => 371.544
[totalViews] => 5
[codecIsForLiveHttp] =>
[url] => http://www.ustream.tv/recorded/33756327
[embedTag] =>
[liveHttpUrl] =>
[imageUrl] => Array
(
[small] => http://static-cdn2.ustream.tv/videopic/0/1/33/33756/33756327/1_14659377_33756327_120x90_b_1:2.jpg
[medium] => http://static-cdn2.ustream.tv/videopic/0/1/33/33756/33756327/1_14659377_33756327_320x240_b_1:2.jpg
)
[sourceChannel] => Array
(
[id] => 14659377
[url] => http://www.ustream.tv/channel/14659377
)
)
[1] => Array
(
[id] => 33756481
[userName] => sachintaware
[title] => gobiggitest
[protected] =>
[description] => gobiggitest
[createdAt] => 2013-06-03 03:37:49
[rating] => 0.000
[lengthInSecond] => 647.580
[totalViews] => 11
[codecIsForLiveHttp] =>
[url] => http://www.ustream.tv/recorded/33756481
[embedTag] =>
[liveHttpUrl] =>
[imageUrl] => Array
(
[small] => http://static-cdn2.ustream.tv/videopic/0/1/33/33756/33756481/1_14659377_33756481_120x90_b_1:3.jpg
[medium] => http://static-cdn2.ustream.tv/videopic/0/1/33/33756/33756481/1_14659377_33756481_320x240_b_1:3.jpg
)
[sourceChannel] => Array
(
[id] => 14659377
[url] => http://www.ustream.tv/channel/14659377
)
)
This is the function I used to go through the array as I want to fetch the [id] => 14659377 which is inside sourceChannel.But I am getting an empty value as a return value.What is the mistake I am making? can anyone please help me with it?
$getUsername = array();
function recursion($array) {
foreach ($array as $key => $value) {
if($key==='sourceChannel'){
$getId = $value['id'];
//print_r($getId);
return $getId;
}
if (is_array($value))
recursion($value);
}
}
$getUsername=recursion($resultsArray);
print_r($getUsername);
Your code is flawed because you need to change
recursion($value);
into
return recursion($value);
The return will take the answer back to the caller until the first caller is reached.
edit:
The lesson here is that your function should ALWAYS return a value. So here is some more elaboration:
function recursion($array) {
if (!is_array($array)) // check if what you're getting is an array!
return null;
foreach ($array as $key => $value) {
if($key==='sourceChannel') {
return $value['id'];
}
if (is_array($value)) {
$result = recursion($value);
if ($result !== null) {
return $result;
}
}
}
return null; // this happens if all recursions are done and sourceChannel was not found
}
You're not doing anything with the return from your recursion call.
It's a bit more complex than simply returning it, because you only want to cascade out if we actually found anything.
Try this:
function recursion($array) {
foreach ($array as $key => $value) {
if($key==='sourceChannel') {
return $value['id'];
}
if (is_array($value)) {
$rc = recursion($value);
if (!is_null($rc)) return $rc;
}
}
return null;
}
First, I added return null; to the end of the function - if we didn't find anything, we return null.
Then, when I recurse, I check the return value... if it's non-null, it means we found something and we want to return it. If it is null, we don't want to return - we want to continue the loop instead.
Try like this
foreach ($array['results'] as $key => $value) {
if($key == "sourceChannel"){
$getId = $value['id'];
//print_r($getId);
return $getId;
}
}
You could use iterators to make your function a whole lot easier:
function findSourceChannel($array)
{
foreach (new RecursiveIteratorIterator(new RecursiveArrayIterator($array)) as $key => $value) {
if ($key == 'sourceChannel') {
return $value['id'];
}
}
return null;
}
That said, I'm not sure why you can't just do a search like this:
foreach ($array['results'] as $result) {
if (isset($result['sourceChannel'])) {
return $result['sourceChannel']['id'];
}
}
return null;
Let's say I have an array like this:
Array
(
[id] => 45
[name] => john
[children] => Array
(
[45] => Array
(
[id] => 45
[name] => steph
[children] => Array
(
[56] => Array
(
[id] => 56
[name] => maria
[children] => Array
(
[60] => Array
(
[id] => 60
[name] => thomas
)
[61] => Array
(
[id] => 61
[name] => michelle
)
)
)
[57] => Array
(
[id] => 57
[name] => luis
)
)
)
)
)
What I'm trying to do is to reset the keys of the array with keys children to 0, 1, 2, 3, and so on, instead of 45, 56, or 57.
I tried something like:
function array_values_recursive($arr)
{
foreach ($arr as $key => $value)
{
if(is_array($value))
{
$arr[$key] = array_values($value);
$this->array_values_recursive($value);
}
}
return $arr;
}
But that reset only the key of the first children array (the one with key 45)
function array_values_recursive($arr)
{
$arr2=[];
foreach ($arr as $key => $value)
{
if(is_array($value))
{
$arr2[] = array_values_recursive($value);
}else{
$arr2[] = $value;
}
}
return $arr2;
}
this function that implement array_values_recursive from array like:
array(
'key1'=> 'value1',
'key2'=> array (
'key2-1'=>'value-2-1',
'key2-2'=>'value-2-2'
)
);
to array like:
array(
0 => 'value1',
1 => array (
0 =>'value-2-1',
1 =>'value-2-2'
)
);
You use a recursive approach but you do not assign the return value of the function call $this->array_values_recursive($value); anywhere. The first level works, as you modify $arr in the loop. Any further level does not work anymore for mentioned reasons.
If you want to keep your function, change it as follows (untested):
function array_values_recursive($arr)
{
foreach ($arr as $key => $value)
{
if (is_array($value))
{
$arr[$key] = $this->array_values_recursive($value);
}
}
if (isset($arr['children']))
{
$arr['children'] = array_values($arr['children']);
}
return $arr;
}
This should do it:
function array_values_recursive($arr, $key)
{
$arr2 = ($key == 'children') ? array_values($arr) : $arr;
foreach ($arr2 as $key => &$value)
{
if(is_array($value))
{
$value = array_values_recursive($value, $key);
}
}
return $arr2;
}
Try this ,
function updateData($updateAry,$result = array()){
foreach($updateAry as $key => $values){
if(is_array($values) && count($values) > 0){
$result[$key] = $this->_updateData($values,$values);
}else{
$result[$key] = 'here you can update values';
}
}
return $result;
}
You can used php fnc walk_array_recursive
Here
I want a function that
searches through my array, and
returns all the
children to a specific node. What is
the most appropriate way to do this?
Will recursion be necessary in this case?
I have previously constructed a few quite complex functions that iterates with or without the help of recursion through multi-dimensional arrays and re-arranging them, but this problem makes me completely stuck and I can't just get my head around it...
Here's my array:
Array
(
[1] => Array (
[id] => 1
[parent] => 0
)
[2] => Array (
[id] => 2
[parent] => 1
)
[3] => Array (
[id] => 3
[parent] => 2
)
)
UPDATE:
The output which I want to get. Sorry for the bad example, but I'll blame it on lack of knowledge on how to format the stuff I need to do :)
function getAllChildren($id) {
// Psuedocode
return $array;
}
getAllChildren(1); // Outputs the following:
Array
(
[2] => Array (
[id] => 2
[parent] => 1
)
[3] => Array (
[id] => 3
[parent] => 2
)
)
$nodes = array( 1 => array ( 'id' => 1,
'parent' => 0
),
2 => array ( 'id' => 2,
'parent' => 1
),
3 => array ( 'id' => 3,
'parent' => 2
)
);
function searchItem($needle,$haystack) {
$nodes = array();
foreach ($haystack as $key => $item) {
if ($item['parent'] == $needle) {
$nodes[$key] = $item;
$nodes = $nodes + searchItem($item['id'],$haystack);
}
}
return $nodes;
}
$result = searchItem('1',$nodes);
echo '<pre>';
var_dump($result);
echo '</pre>';
Non-recursive version of the searchItem() function:
function searchItem($needle,$haystack) {
$nodes = array();
foreach ($haystack as $key => $item) {
if (($item['parent'] == $needle) || array_key_exists($item['parent'],$nodes)) {
$nodes[$key] = $item;
}
}
return $nodes;
}
(assumes ordering of the parents/children, so a child node isn't included in the array unless the parent is already there)
<?php
function searchItem($needle)
{
foreach ($data as $key => $item)
{
if ($item['id'] == $needle)
{
return $key;
}
}
return null;
}
?>
Check out the array_walk_recursive() function in PHP:
http://www.php.net/manual/en/function.array-walk-recursive.php