I have an array of key names of variable length and I want to use those names to assign a value to an array
for example, I have an array that lists the number of cars and bikes of different makes:
$vehicles = [
'cars' => Array
(
'suzuki' => Array
(
'wagon' => 4,
'baleno' => 2
),
'honda' => Array
(
'civic' => 6
)
),
'bikes' => array
(
'raleigh' => 3,
'scott' => 3
)
];
I also have several arrays of key names along with values to put in the main array:
$keys1 = ['cars', 'honda', 'jazz'];
$value1 = 3;
$keys2 = ['bikes', 'scott'];
$value2 = 1;
$keys3 = ['motorbikes', 'harley-davidson', 'dyna', 'street-bob'];
$value3 = 2;
After inputting all these values the array should look like this:
$vehicles = [
'cars' => Array
(
'suzuki' => Array
(
'wagon' => 4,
'baleno' => 2
),
'honda' => Array
(
'civic' => 6,
'jazz' => 3
)
),
'bikes' => array
(
'raleigh' => 3,
'scott' => 1
),
'motorbikes' => Array
(
'harley-davidson' => Array
(
'dyna' => Array
(
'street-bob' => 2
)
)
)
];
So the first array adds a $key => $value
pair where there wasn't one before. The second one replaces the value of the key at the end of $array2
and the last one creates a new array when there isn't one to begin with.
How can I populate the array in this way?
eval()
would solve all my problems but the arrays are created from html and so it is a huge security risk.
You could transform your $keys
array in the same format as your $vehicles
and then replace them recursively :
$vehicles = [
'cars' => [
'suzuki' => [
'wagon' => 1,
'boleno' => 2
]
],
'bikes' => [
'scott' => 3
]
];
$keys = ['cars', 'honda', 'jazz'];
$value = 3;
function addValues($vehicles, $keys, $value)
{
$formatted = formatArray($keys, $value);
return array_replace_recursive($vehicles, $formatted);
}
function formatArray($array, $value)
{
$format = function ($carry, $item) {
return [$item => $carry];
};
return array_reduce(array_reverse($array), $format, $value);
}
$vehicles = addValues($vehicles, $keys, $value);
var_dump($vehicles);
Output:
array (size=2)
'cars' =>
array (size=2)
'suzuki' =>
array (size=2)
'wagon' => int 1
'boleno' => int 2
'honda' =>
array (size=1)
'jazz' => int 3
'bikes' =>
array (size=1)
'scott' => int 3
The convenient way(on my opinion) to construct a key/value pairs list would be as the following:
// $vehicles is your initial array
$key_paths = [
['key_path' => ['cars', 'honda', 'jazz'], 'value' => 3],
['key_path' => ['bikes', 'scott'], 'value' => 1],
['key_path' => ['motorbikes', 'harley-davidson', 'dyna', 'street-bob'], 'value' => 2],
];
And here is the solution using array_slice
function and references:
foreach ($key_paths as $kPath) {
$current = null;
foreach (array_slice($kPath['key_path'], 0, -1) as $key) {
if (is_null($current)) {
if (!isset($vehicles[$key])) $vehicles[$key] = [];
$current = &$vehicles[$key];
} else {
if (!isset($current[$key])) $current[$key] = [];
$current = &$current[$key];
}
}
$current[end($kPath['key_path'])] = $kPath['value'];
unset($current); // unsetting reference
}
print_r($vehicles);
The output:
Array
(
[cars] => Array
(
[suzuki] => Array
(
[wagon] => 4
[baleno] => 2
)
[honda] => Array
(
[civic] => 6
[jazz] => 3
)
)
[bikes] => Array
(
[raleigh] => 3
[scott] => 1
)
[motorbikes] => Array
(
[harley-davidson] => Array
(
[dyna] => Array
(
[street-bob] => 2
)
)
)
)