tags:

views:

67

answers:

3

Hi,

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

+1  A: 

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')

Your choice of "You can use this baby:" really struck me as weird...
jordanstephens
should i edit it out?
+1  A: 

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') );
pygorex1
you can do this without the `global` var and it'd be a much better example if you did.
Mark E
@Mark: It's a simple example - and can be easily refactored to use `static $complete` variable declaration instead. Feel free to post your own solution!
pygorex1
A: 
vlad b.
Why did i get a -1 , i'm curious ?
vlad b.