use strings to access (potentially large) multidimensional arrays
Considering $vars
being your variables you would like to get one['one-one']
or two['two-two']['more']
from (Demo):
$vars = function($str) use ($vars)
{
$c = function($v, $w) {return $w ? $v[$w] : $v;};
return array_reduce(preg_split('~\[\'|\'\]~', $str), $c, $vars);
};
echo $vars("one['one-one']"); # hello
echo $vars("two['two-two']['more']"); # tea-time!
This is lexing the string into key tokens and then traverse the $vars
array on the keyed values while the $vars
array has been turned into a function.
Older Stuff:
Overload the array with a function that just eval's:
$vars = array(
'one' => array(
'one-one' => "hello",
'one-two' => "goodbye"
),
'two' => array(
'two-one' => "foo",
'two-two' => "bar"
)
);
$vars = function($str) use ($vars)
{
return eval('return $vars'.$str.';');
};
echo $vars("['one']['one-two']"); # goodbye
If you're not a fan of eval, change the implementation:
$vars = function($str) use ($vars)
{
$r = preg_match_all('~\[\'([a-z-]+)\']~', $str, $keys);
$var = $vars;
foreach($keys[1] as $key)
$var = $var[$key];
return $var;
};
echo $vars("['one']['one-two']"); # goodbye
PHP get value from armultidimensional array based on array with keys
Try this approach:
$arr = [
"something" => [
'something_else' => [
"another_thing" => "boo"
]
],
"something2" => [
'something_elseghf' => [
"another_thingfg" => [
"hi" => "bye"
]
]
],
"info" => [
'something_else2' => [
"another_thingh" => "boo"
]
],
];
$keyArr = ["something2", 'something_elseghf', "another_thingfg", "hi"];
$cursor = $arr;
foreach ($keyArr as $key) {
$cursor = $cursor[$key];
}
echo $cursor;
Will echo
bye
UPDATE:
If you want to change a value within multi-dimentional array, then use a recursive function, like this:
function changeValue($array, $path, $value) {
if (empty($path)) {
return $value;
}
$key = array_shift($path);
$array[$key] = changeValue($array[$key], $path, $value);
return $array;
}
$arr = [
"something" => [
'something_else' => [
"another_thing" => "boo"
]
],
"something2" => [
'something_elseghf' => [
"another_thingfg" => [
"hi" => "bye"
]
]
],
"info" => [
'something_else2' => [
"another_thingh" => "boo"
]
],
];
$keyArr = ["something2", 'something_elseghf', "another_thingfg", "hi"];
$changedArray = changeValue($arr, $keyArr, 'New value!');
print_r($changedArray);
Will output
Array
(
[something] => Array
(
[something_else] => Array
(
[another_thing] => boo
)
)
[something2] => Array
(
[something_elseghf] => Array
(
[another_thingfg] => Array
(
[hi] => New value!
)
)
)
[info] => Array
(
[something_else2] => Array
(
[another_thingh] => boo
)
)
)
PHP: Use array to get value in another, multidimensional array
You might want to create some kind of helper function, where you iterate over parts of your path while keeping track of your temporary result:
function deep_array_get(array $path, array $subject) {
$result = $subject;
foreach ($path as $p) {
$result = $result[$p];
}
return $result;
}
Example:
$p = ["a", "b", "c"];
$s = [1, 2, "a" => [3, 4, "b" => ["c" => 5]]];
var_dump(deep_array_get($p, $s));
// Result: int(5)
In your exact usecase it would be used something like this:
$path = ['neighborhood', 'street', 'house'];
$subject = get_option($options_id);
$result = deep_array_get($path, $subject);
How to access and manipulate multi-dimensional array by key names / path?
Assuming $path
is already an array via explode
(or add to the function), then you can use references. You need to add in some error checking in case of invalid $path
etc. (think isset
):
$key = 'b.x.z';
$path = explode('.', $key);
Getter
function get($path, $array) {
//$path = explode('.', $path); //if needed
$temp =& $array;
foreach($path as $key) {
$temp =& $temp[$key];
}
return $temp;
}
$value = get($path, $arr); //returns NULL if the path doesn't exist
Setter / Creator
This combination will set a value in an existing array or create the array if you pass one that has not yet been defined. Make sure to define $array
to be passed by reference &$array
:
function set($path, &$array=array(), $value=null) {
//$path = explode('.', $path); //if needed
$temp =& $array;
foreach($path as $key) {
$temp =& $temp[$key];
}
$temp = $value;
}
set($path, $arr);
//or
set($path, $arr, 'some value');
Unsetter
This will unset
the final key in the path:
function unsetter($path, &$array) {
//$path = explode('.', $path); //if needed
$temp =& $array;
foreach($path as $key) {
if(!is_array($temp[$key])) {
unset($temp[$key]);
} else {
$temp =& $temp[$key];
}
}
}
unsetter($path, $arr);
*The original answer had some limited functions that I will leave in case they are of use to someone:
Setter
Make sure to define $array
to be passed by reference &$array
:
function set(&$array, $path, $value) {
//$path = explode('.', $path); //if needed
$temp =& $array;
foreach($path as $key) {
$temp =& $temp[$key];
}
$temp = $value;
}
set($arr, $path, 'some value');
Or if you want to return the updated array (because I'm bored):
function set($array, $path, $value) {
//$path = explode('.', $path); //if needed
$temp =& $array;
foreach($path as $key) {
$temp =& $temp[$key];
}
$temp = $value;
return $array;
}
$arr = set($arr, $path, 'some value');
Creator
If you wan't to create the array and optionally set the value:
function create($path, $value=null) {
//$path = explode('.', $path); //if needed
foreach(array_reverse($path) as $key) {
$value = array($key => $value);
}
return $value;
}
$arr = create($path);
//or
$arr = create($path, 'some value');
For Fun
Constructs and evaluates something like $array['b']['x']['z']
given a string b.x.z
:
function get($array, $path) {
//$path = explode('.', $path); //if needed
$path = "['" . implode("']['", $path) . "']";
eval("\$result = \$array{$path};");
return $result;
}
Sets something like $array['b']['x']['z'] = 'some value';
:
function set(&$array, $path, $value) {
//$path = explode('.', $path); //if needed
$path = "['" . implode("']['", $path) . "']";
eval("\$array{$path} = $value;");
}
Unsets something like $array['b']['x']['z']
:
function unsetter(&$array, $path) {
//$path = explode('.', $path); //if needed
$path = "['" . implode("']['", $path) . "']";
eval("unset(\$array{$path});");
}
How to access a multidimensinal PHP array, when path (level) to value is dynamic changing?
Here's a small class I wrote that would determine the number of dimensions. You could easily modify it to do whatever you wanted, or just use the number it returns to guide your own function:
class DimensionCounter {
var $i;
public function count($array) {
$this->i = 1;
return $this->readArray($array);
}
private function readArray($array) {
foreach($array as $value) {
if (is_array($value)) {
$this->i++;
$this->readArray($value);
}
return $this->i;
}
}
}
In your case, $counter = new DimensionCounter();
$num = $counter->count($value);
would give you the number of dimensions.
How to create a C++ multidimensional array of names with basic types
You can, e.g., get an array of pointers to null-terminated strings:
const char* names_array[] = { "Bob", "Carl" };
and then
std::printf("%s", names_array[0]);
std::printf("%s", names_array[1]);
The problem with your attempt
char names_array[2] = {"Bob","Carl"};
is that you declare names_array
to be an array of characters. This should never compile because what the = {"Bob","Carl"}
essentially attempts to do is initialize each character in that array of characters with an entire array of characters of its own. A character is just a character, you cannot assign an entire array of characters to just an individual character. More precisely, initialization of a character array from a string literal is a special case of initialization [dcl.init.string] that allows a single string literal to be used to initialize an entire character array (because anything else doesn't make sense). What you actually want would be something more like an array of character arrays. However, the problem there is that you'd have to effectively pick a fixed maximum length for all strings in the array:
char names_array[][5] = { "Bob", "Carl" }; // each subarray is 5 characters in length
which would be potentially wasteful. You can flatten a series of multiple strings into one long array and then index into that, like you did with your first approach. The downside of that, as you've found out, is that you then need to know where each string starts in that array…
If you just want an array of string constants, a more modern C++ approach would be something like this:
#include <string_view>
using namespace std::literals;
constexpr std::string_view names[] = {
"Bob"sv,
"Carl"sv
};
The advantage of std::string_view
is that it also has information about the length of the string. However, while std::string_view
is compatible with most of the C++ standard library facilities that handle strings, it's not so simple to use it together with functions that expect C-style null-terminated strings. If you need null-terminated strings, I'd suggest to simply use an array of pointers to strings as shown at the very beginning of this answer…
Related Topics
Read Large Data from CSV File in PHP
Why Doesn't File_Get_Contents Work
Replacing MySQL_* Functions with Pdo and Prepared Statements
Magento Upgrade Takes Too Long and Never Completes
How to See Which Checkbox Is Checked
PHP Foreach Loop Through Multidimensional Array
What Does ${ } Mean in PHP Syntax
Manipulate an Archive in Memory with PHP (Without Creating a Temporary File on Disk)
How to Count Days Between Two Dates in PHP
Expected Response Code 220 But Got Code "", with Message "" in Laravel
How Exactly Does If($Variable) Work
How to Search in an Array with Preg_Match
How to Get PHP to Produce a Backtrace Upon Errors
How to Get System Environment Variables into PHP While Running Cli & Apache2Handler
Is There a PHP Sandbox, Something Like Jsfiddle Is to Js