I'm trying to find (or create) a function. I have a multidimensional array:
$data_arr = [
"a" => [
"aa" => "abfoo",
"ab" => [
"aba" => "abafoo",
"abb" => "abbfoo",
"abc" => "abcfoo"
],
"ac" => "acfoo"
],
"b" => [
"ba" => "bafoo",
"bb" => "bbfoo",
"bc" => "bcfoo"
],
"c" => [
"ca" => "cafoo",
"cb" => "cbfoo",
"cc" => "ccfoo"
]
];
And I want to access a value using a single-dimentional array, like this:
$data_arr_call = ["a", "ab", "abc"];
someFunction( $data_arr, $data_arr_call ); // should return "abcfoo"
This seems like there's probably already a function for this type of thing, I just don't know what to search for.
Try this
function flatCall($data_arr, $data_arr_call){
$current = $data_arr;
foreach($data_arr_call as $key){
$current = $current[$key];
}
return $current;
}
The $current
variable gets iteratively built up, like so:
flatCall($data_arr, ['a','ab','abc']);
1st iteration: $current = $data_arr['a'];
2nd iteration: $current = $data_arr['a']['ab'];
3rd iteration: $current = $data_arr['a']['ab']['abc'];
You could also do if ( isset($current) ) ...
in each iteration to provide an error-check.
You can use this function that avoids the copy of the whole array (using references), is able to return a NULL value (using array_key_exists
instead of isset
), and that throws an exception when the path doesn't exist:
function getItem(&$array, $path) {
$target = &$array;
foreach($path as $key) {
if (array_key_exists($key, $target))
$target = &$target[$key];
else throw new Exception('Undefined path: ["' . implode('","', $path) . '"]');
}
return $target;
}
demo:
$data = [
"a" => [
"aa" => "abfoo",
"ab" => [
"aba" => "abafoo",
"abb" => NULL,
"abc" => false
]
]
];
var_dump(getItem($data, ['a', 'ab', 'aba']));
# string(6) "abafoo"
var_dump(getItem($data, ['a', 'ab', 'abb']));
# NULL
var_dump(getItem($data, ['a', 'ab', 'abc']));
# bool(false)
try {
getItem($data, ['a', 'ab', 'abe']);
} catch(Exception $e) {
echo $e->getMessage();
}
# Undefined path: ["a","ab","abe"]
Note that this function can be improved, for example you can test if the parameters are arrays.
Wanted to post an even more elegant solution: array_reduce
$data_arr = [
"a" => [
...
"ab" => [
...
"abc" => "abcfoo"
],
...
],
...
];
$result = array_reduce(["a", "ab", "abc"], function($a, $b) {
return $a[$b];
}, $data_arr);
// returns "abcfoo"
I've been using Javascript's Array.reduce()
a lot lately in updating some legacy code to ES6:
JS:
const data_obj = {...};
let result = ['a','ab','abc'].reduce((a, b) => a[b], data_obj);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With