0

I receive a large multi-dimensional array from an API. I save the array into a class property and then I use a magic getter to disguise the array and have end users use keys as properties ($class->key ==> $class->data['key']).

Now the array I am dealing with is very much multi-dimensional and I need keys on different "levels" or layers. Imagine the array has two branches with multiple layers.

The keys I am looking for are usually the top level.

I will try to illustrate this:

Array
    baseKey
        key1
            value1
        key2
            value2
        key3
            subKey1
                value3
            subKey2
                value4
    key4
        value5
    key5
        subKey3
            value6
    key6
        subKey4
            subSubKey1
                value7

I am looking for a function that I can give any key to, including baseKey, key, subKey and subSubKey and that will return the respective value for the first key that matches.

So as an example:

awesomeFindByKey('key2') 
    ==> value2

awesomeFindByKey('subKey4') 
    ==> array('subSubKey1' => 'value7')

awesomeFindByKey('key6') 
    ==> array('subKey4' => array('subSubKey1' => 'value7'))

Is there a function for this or will I have to write one myself? Does anybody maybe have a function that does this?

I hope it was understandable. Thanks.

7
  • 2
    does recursion ring a bell? Commented Jan 18, 2015 at 11:16
  • I was wondering if there is a function that would allow me to not have to array_map. Commented Jan 18, 2015 at 11:20
  • You can write your own function withouth using array_map because its not that fast. Commented Jan 18, 2015 at 11:32
  • What would that look like? foreach doesn't recurse. So what would I use? Commented Jan 18, 2015 at 11:36
  • Is this array stored in a class? Commented Jan 18, 2015 at 11:39

1 Answer 1

1

Here is very simple sample implementation:

// sample class
class A {

  // the data array
  protected $data = array();

  // init
  public function __construct($data = null) {
    $this->setData($data);
  }

  // recursive search of a key
  private function searchLayer($key, $layer, $searchKey) {
    // return the layer if we have a match
    if ((string) $key === (string) $searchKey) return $layer;

    // loop the array if we need to go deeper
    if ((array) $layer === $layer) {
        foreach ($layer as $k => $v) {
            // apply recursition
            $result = $this->searchLayer($k, $v, $searchKey);

            // return on match
            if (!empty($result)) return $result;
        }
    }

    // nothing found - recursion ended here
    return null;
  }

  // returns the value of the data array with the given key
  public function getValueByKey($searchKey) {
    echo '<br>search by key: ' . $searchKey . '<br>';

    // check if we have a match
    foreach ($this->data as $key => $layer) {
        // resolve layer
        $result = $this->searchLayer($key, $layer, $searchKey);

        // return on match
        if (!empty($result)) return $result;
    }

    // nothing found
    return null;
  }

  // set the data
  public function setData($data) {
    if ((array) $data === $data) $this->data = $data;
  }

  // possible extension
  public function __get($key) {
    return $this->getValueByKey($key);
  }
}

// create the object of the class 'a'
$a = new A();

// set the data
$a->setData(array(
  'value1',
  'key2' => 'value2',
  'key3' => array(
    'subkey31' => 'value31',
    'subkey32' => 'value32'
  )
));

var_dump($a->getValueByKey('subkey32'));
var_dump($a->subkey32);

Output: string(7) "value32" string(7) "value32"

Test it here: http://writecodeonline.com/php just paste the code and hit run.

EDIT

Of course this is a very basic example - you could also use some of the given php-classes like others already said for example ArrayAccess.

Sign up to request clarification or add additional context in comments.

2 Comments

It would appear $a->subkey32 does not work. Same for $a->subkey31 of course. This would however be essential.
If this works for your purpose you may accept the answer. Otherwise please tell me what you want to change. Thank you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.