phparrayslaravelmappinggrouping

Group 2d array by two columns and concatenate values mapped to first level keys


I have an array of opening/closing hours of a store:

array:3 [▼
  1 => array:2 [▼
    "opens_at" => "10:00"
    "closes_at" => "18:00"
  ]
  2 => array:2 [▼
    "opens_at" => "10:00"
    "closes_at" => "18:00"
  ]
  3 => array:2 [▼
    "opens_at" => "10:00"
    "closes_at" => "18:00"
  ]
  4 => array:2 [▼
    "opens_at" => "14:00"
    "closes_at" => "17:00"
  ]
  5 => array:2 [▼
    "opens_at" => "14:00"
    "closes_at" => "17:00"
  ]
  6 => array:2 [▼
    "opens_at" => "18:00"
    "closes_at" => "19:00"
  ]
]

The keys of the array from 1 to 6 relate to the day of the week (Monday to Saturday). I'm using a simple Enum class for this:

class WeekDays
{
    const MONDAY = 1;
    const TUESDAY = 2;
    const WEDNESDAY = 3;
    const THURSDAY = 4;
    const FRIDAY = 5;
    const SATURDAY = 6;
    const SUNDAY = 7;
}

So, I need to get a result that is grouping the days having similar opening & closing hours as follow:

[
    Mo,Tu,We 10:00-18:00,
    Th,Fr 14:00-17:00
    Sa 18:00-19:00
]

I can't figure out how to group by opens_at & closes_at to get the formatted result above.


Solution

  • Not a very elegant solution but it could give you a hint on how you can solve it yourself:

    <?php
    
    $a = [
      1 => [
        "opens_at" => "10:00",
        "closes_at" => "18:00"
      ],
      2 => [
        "opens_at" => "10:00",
        "closes_at" => "18:00"
      ],
      3 => [
        "opens_at" => "10:00",
        "closes_at" => "18:00"
      ],
      4 => [
        "opens_at" => "14:00",
        "closes_at" => "17:00"
      ],
      5 => [
        "opens_at" => "14:00",
        "closes_at" => "17:00"
      ],
      6 => [
        "opens_at" => "18:00",
        "closes_at" => "19:00"
      ]
    ];
    
    $groups = [];
    
    foreach($a as $dayNumber => $w){
        if(!array_key_exists($w['opens_at'] . '-' . $w['closes_at'], $groups)){
            $groups[$w['opens_at'] . '-' . $w['closes_at']] = [];
        }
    
        $groups[$w['opens_at'] . '-' . $w['closes_at']][] = $dayNumber;
    }
    
    $res = array_map(function($v){
        return implode(', ', $v);
    }, $groups);
    
    var_dump(array_flip($res));
    

    Results in:

    array(3) { ["1, 2, 3"]=> string(11) "10:00-18:00" ["4, 5"]=> string(11) "14:00-17:00" [6]=> string(11) "18:00-19:00" }
    

    https://3v4l.org/p4oa6