2

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'] . "\n";
    echo ' - ' . $d['groups_label'] . "\n";
    echo ' -- ' . $d['filters_label'] . "\n";
}

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'] . "\n";
       echo "-" . $d['groups_label'] . "\n";
   }
}

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

3 Answers 3

7

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'];
}

DEMO

Sign up to request clarification or add additional context in comments.

Comments

2

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'] . "\n";   

       }
       if ($data[$key-1]['groups_label'] !== $d['groups_label']) {
           echo "-" . $d['groups_label'] . "\n";
       }
   }
   else
   {
       //special case to deal with first row where $key-1 doesn't exist
       echo $d['regulations_label'] . "\n";   
       echo "-" . $d['groups_label'] . "\n";
   }
   echo ' -- ' . $d['filters_label'] . "\n";
}

Demo: https://3v4l.org/ihYVj

2 Comments

This is a good solution as it causes fewer issues than the accepted answer with the memory overhead from the $group array. It's giving a Notice: Undefined offset: -1 error though.
@Andy sorry about that... see updated demo and code sample above. It's just an issue with the first row, because obviously when $key is 0, there's no array index at $key-1!
0

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'] . "\n";
        $last_reg = $reg['regulations_label'];
        $last_grp = NULL;
        $last_filter = NULL;
    }
    if ( $last_grp != $reg['groups_label']) {
        echo "\t - " . $reg['groups_label'] . "\n";
        $last_grp = $reg['groups_label'];
    }
    echo "\t\t - " . $reg['filters_label'] . "\n";
}

RESULT:

Europe
     - G1
         - FF1
         - FF900
         - FF324234
     - G2
         - FF23942
America
     - G29
         - FF3242
         - FF78978
         - FF48395043
Asia
     - G2000
         - FF7

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.