Reputation: 4106
I have a deep and long array (matrix). I only know the product ID. How found way to product?
Sample an array of (but as I said, it can be very long and deep):
Array(
[apple] => Array(
[new] => Array(
[0] => Array([id] => 1)
[1] => Array([id] => 2))
[old] => Array(
[0] => Array([id] => 3)
[1] => Array([id] => 4))
)
)
I have id: 3, and i wish get this: apple, old, 0
Thanks
Upvotes: 4
Views: 223
Reputation: 11
I tried this for my programming exercise.
<?php
$data = array(
'apple'=> array(
'new'=> array(array('id' => 1), array('id' => 2), array('id' => 5)),
'old'=> array(array('id' => 3), array('id' => 4))
),
);
####print_r($data);
function deepfind($data,$findfor,$depth = array() ){
foreach( $data as $key => $moredata ){
if( is_scalar($moredata) && $moredata == $findfor ){
return $depth;
} elseif( is_array($moredata) ){
$moredepth = $depth;
$moredepth[] = $key;
$isok = deepfind( $moredata, $findfor, $moredepth );
if( $isok !== false ){
return $isok;
}
}
}
return false;
}
$aaa = deepfind($data,3);
print_r($aaa);
Upvotes: 0
Reputation: 695
If you create the array once and use it multiple times i would do it another way...
$id_to_info=array();
$id_to_info[1]=&array['apple']['new'][0];
$id_to_info[2]=&array['apple']['new'][2];
Upvotes: -1
Reputation: 5846
You can use this baby:
function getById($id,$array,&$keys){
foreach($array as $key => $value){
if(is_array( $value )){
$result = getById($id,$value,$keys);
if($result == true){
$keys[] = $key;
return true;
}
}
else if($key == 'id' && $value == $id){
$keys[] = $key; // Optional, adds id to the result array
return true;
}
}
return false;
}
// USAGE:
$result_array = array();
getById( 3, $products, $result_array);
// RESULT (= $result_array)
Array
(
[0] => id
[1] => 0
[2] => old
[3] => apple
)
The function itself will return true
on success and false
on error, the data you want to have will be stored in the 3rd parameter.
You can use array_reverse()
, link, to reverse the order and array_pop()
, link, to remove the last item ('id')
Upvotes: 1
Reputation: 38308
Recursion is the answer for this type of problem. Though, if we can make certain assumptions about the structure of the array (i.e., 'id' always be a leaf node with no children) there's further optimizations possible:
<?php
$a = array(
'apple'=> array(
'new'=> array(array('id' => 1), array('id' => 2), array('id' => 5)),
'old'=> array(array('id' => 3), array('id' => 4, 'keyname' => 'keyvalue'))
),
);
// When true the complete path has been found.
$complete = false;
function get_path($a, $key, $value, &$path = null) {
global $complete;
// Initialize path array for first call
if (is_null($path)) $path = array();
foreach ($a as $k => $v) {
// Build current path being tested
array_push($path, $k);
// Check for key / value match
if ($k == $key && $v == $value) {
// Complete path found!
$complete= true;
// Remove last path
array_pop($path);
break;
} else if (is_array($v)) {
// **RECURSION** Step down into the next array
get_path($v, $key, $value, $path);
}
// When the complete path is found no need to continue loop iteration
if ($complete) break;
// Teardown current test path
array_pop($path);
}
return $path;
}
var_dump( get_path($a, 'id', 3) );
$complete = false;
var_dump( get_path($a, 'id', 2) );
$complete = false;
var_dump( get_path($a, 'id', 5) );
$complete = false;
var_dump( get_path($a, 'keyname', 'keyvalue') );
Upvotes: 1