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?
2
Answers
You’re right that recursion would be a good approach. First of all I would suggest preserving the original array as-is, so that you don’t have to think about the various modifications it will go through as you process it. To mark parts of it as already processed, you can use an index (as suggested by your
target_index
argument) or pass slices of the array to the recursive calls.I think you are close, you just need to do something with the rest of the array (if there are more elements to process) at the end of the function.
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)
Or with the same logic in a different orientation: (Demo)