Apologies if this has been asked but I can't find a solution that meets my needs.
I have an array in a PHP 7 application as follows:
$data = [
0 => [
'regulations_label' => 'Europe',
'groups_label' => 'G1',
'filters_label' => 'FF1'
],
1 => [
'regulations_label' => 'Europe',
'groups_label' => 'G1',
'filters_label' => 'FF900'
],
2 => [
'regulations_label' => 'Europe',
'groups_label' => 'G1',
'filters_label' => 'FF324234'
],
3 => [
'regulations_label' => 'Europe',
'groups_label' => 'G2',
'filters_label' => 'FF23942'
],
4 => [
'regulations_label' => 'America',
'groups_label' => 'G29',
'filters_label' => 'FF3242'
],
5 => [
'regulations_label' => 'America',
'groups_label' => 'G29',
'filters_label' => 'FF78978'
],
6 => [
'regulations_label' => 'America',
'groups_label' => 'G29',
'filters_label' => 'FF48395043'
],
7 => [
'regulations_label' => 'Asia',
'groups_label' => 'G2000',
'filters_label' => 'FF7'
],
// ...
];
The output I want to achieve is like this:
Europe
- G1
-- FF1
-- FF900
- G2
-- FF23942
America
- G29
-- FF3242
-- FF48395043
Asia
- G2000
-- FF7
Essentially all it's doing is outputting the array in a structured format such that it shows the regulations_label
followed by any corresponding groups_label
and then any filters_label
.
It's simple enough to loop through the entire array, e.g.
foreach ($data as $d) {
echo $d['regulations_label'] . "
";
echo ' - ' . $d['groups_label'] . "
";
echo ' -- ' . $d['filters_label'] . "
";
}
However this introduces "duplicate" headings for regulations_label
and groups_label
because it's printing every single key. But I don't see how I can check if this has changed during the foreach
statement because $d
is always the current element.
I was attempting to do a check based on the previous array key:
foreach ($data as $key => $d) {
if ($data[$key-1]['regulations_label'] !== $d['regulations_label']) {
echo $d['regulations_label'] . "
";
echo "-" . $d['groups_label'] . "
";
}
}
The trouble is that this then just prints 1 groups_label
so I'd end up with - for example:
Europe
- G1
America
...
It wouldn't get as far as "G2".
I can't help but think I'm going about this in a bizarre way. Can anyone advise a better solution?
Background info: The data I receive in $data
isn't something I can modify because that format is required for the use case which is a feature in an application like this: jQuery load more data on scroll
you can use foreach
and group by using regulations_label
and groups_label
$group = [];
foreach($data as $v){
$group[$v['regulations_label']][$v['groups_label']][] = $v['filters_label'];
}
In the simplest case you just need to add some if
statements as you'd started to do, but you also have to make sure they only stop the relevant bit from printing - your version was suppressing the whole output, instead of just the top-level label:
foreach ($data as $key => $d) {
if ($key > 0) {
if ($data[$key-1]['regulations_label'] !== $d['regulations_label']) {
echo $d['regulations_label'] . "
";
}
if ($data[$key-1]['groups_label'] !== $d['groups_label']) {
echo "-" . $d['groups_label'] . "
";
}
}
else
{
//special case to deal with first row where $key-1 doesn't exist
echo $d['regulations_label'] . "
";
echo "-" . $d['groups_label'] . "
";
}
echo ' -- ' . $d['filters_label'] . "
";
}
Demo: https://3v4l.org/ihYVj
All you need to do is remember what you last processed and then adda couple of IF's
$data = [
0 => ['regulations_label' => 'Europe','groups_label' => 'G1','filters_label' => 'FF1'],
1 => ['regulations_label' => 'Europe','groups_label' => 'G1','filters_label' => 'FF900'],
2 => ['regulations_label' => 'Europe','groups_label' => 'G1','filters_label' => 'FF324234'],
3 => ['regulations_label' => 'Europe','groups_label' => 'G2','filters_label' => 'FF23942'],
4 => ['regulations_label' => 'America','groups_label' => 'G29','filters_label' => 'FF3242'],
5 => ['regulations_label' => 'America','groups_label' => 'G29','filters_label' => 'FF78978'],
6 => ['regulations_label' => 'America','groups_label' => 'G29','filters_label' => 'FF48395043'],
7 => ['regulations_label' => 'Asia','groups_label' => 'G2000','filters_label' => 'FF7']
];
$last_reg = NULL;
$last_grp = NULL;
foreach ($data as $reg) {
if ( $last_reg != $reg['regulations_label']) {
echo $reg['regulations_label'] . "
";
$last_reg = $reg['regulations_label'];
$last_grp = NULL;
$last_filter = NULL;
}
if ( $last_grp != $reg['groups_label']) {
echo "\t - " . $reg['groups_label'] . "
";
$last_grp = $reg['groups_label'];
}
echo "\t\t - " . $reg['filters_label'] . "
";
}
RESULT:
Europe
- G1
- FF1
- FF900
- FF324234
- G2
- FF23942
America
- G29
- FF3242
- FF78978
- FF48395043
Asia
- G2000
- FF7