I have an input array like this
$input = [
["relation" => "OR"],
["color" => 'green'],
["color" => 'yellow'],
["relation" => "AND"],
["color" => 'black'],
["color" => 'orange'],
["relation" => "OR"],
["color" => 'blue'],
["color" => 'violet'],
];
Desired result:
$output = array(
'relation' => 'OR',
array(
"color" => 'green'
),
array(
"color" => 'yellow'
),
array(
"relation" => "AND",
array(
"color" => "black"
),
array(
"color" => "orange"
),
array(
"relation" => "OR",
array(
"color" => "blue"
),
array(
"color" => "violet"
),
)
)
);
I believe I need to do make recursive function to handle this.
I have this but only works for a single level
function generate_nested_array($array, $nested_tax_query = array(), $target_index = 0)
{
//the first element is always the relation
$nested_tax_query['relation'] = $array[0]['relation'];
// unset the first element as it is not needed anymore
unset($array[0]);
$len = count($array);
// reindex the array
$array = array_values($array);
foreach ($array as $element_key => $element) {
if (isset($element['relation'])) {
$target_index = $element_key;
break;
}
}
// put everything below the target index into the target index and leave the rest as it is
for ($i = 0; $i < $len - 1; $i++) {
if ($i < $target_index) {
$nested_tax_query[] = $array[$i];
} else {
$nested_tax_query[$target_index][] = $array[$i];
}
}
// last item in the nested array
$len_nested = count($nested_tax_query);
// last item in the in the nested array
$last_item_in_nested_array = $nested_tax_query[$len_nested - 2];
return $nested_tax_query;
}
Is my approach correct?
I did not see the point in using recursion. I found reference variables to be a more intuitive approach. Every time you encounter a new relation
, change the "reference" to be the new/last element where the reference was.
When not dealing with relation
data, you can safely push data directly into the current reference variable and it will be exactly where you wish it to be.
Code: (Demo)
$ref = [];
$result =& $ref;
foreach ($input as $row) {
if (key($row) !== 'relation') { // populate current level
$ref[] = $row; // push color into reference
continue;
}
if ($ref) { // not the first relation encountered
$ref =& $ref[]; // set $ref to point to new deeper subarray
}
$ref = $row; // push relation
}
var_export($result);
Or with the same logic in a different orientation: (Demo)
$ref = [];
$result =& $ref;
foreach ($input as $row) {
if (key($row) === 'relation') {
if ($ref) { // not the first relation encountered
$ref =& $ref[]; // set $ref to point to new deeper subarray
}
$ref = $row; // push relation
} else {
$ref[] = $row; // push color into reference
}
}
var_export($result);