0

I have an input array which contains arrays of day and time data:

$temp = Array
(
    [0] => Array
        (
            [day] => Tuesday
            [time] => 07:44 pm - 08:44 pm
        )

    [1] => Array
        (
            [day] => Tuesday
            [time] => 04:00 am - 04:25 am
        )

    [2] => Array
        (
            [day] => Sunday
            [time] => 04:00 am - 04:25 am
        )

    [3] => Array
        (
            [day] => Sunday
            [time] => 04:00 am - 04:25 am
        )

    [4] => Array
        (
            [day] => Friday
            [time] => 04:00 am - 04:25 am
        )

    [5] => Array
        (
            [day] => Friday
            [time] => 04:00 am - 04:25 am
        )
)

Now I want to group the common times display as one element and if the time is the same for more than one day then it's should display one entry. So what is the best way to achieve the desired result without making this too complex?

Array
(
    [0] => Array
        (
            [day] => Tuesday
            [time] => 04:00 am - 04:25 am & 07:44 pm - 08:44 pm
        )

    [1] => Array
        (
            [day] => Friday & Sunday
            [time] => 04:00 am - 04:25 am
        )
)

Here it's what I have done:

$final = [];
foreach ($temp as $val) {
     $final[strtolower($val['day'])][] = $val['time'];
}
foreach ($final as $k => $v) {
    sort($v);
    $v = array_unique($v);
    $last = array_pop($v);
    $final[$k] = [
       'day' => $k,
       'time' => count($v) ? implode(", ", $v) . " & " . $last : $last,
    ];
}
6
  • @aman-maurya I don't get the logic by which the elements should be merged? In one situation it's merged by day, in other - by time. Commented Nov 28, 2017 at 7:31
  • What if day is same and time is also same.. Are not you care about this condition @AmanMaurya Commented Nov 28, 2017 at 7:34
  • @neodan I hv remove the duplicate time and combine as one element.. Commented Nov 28, 2017 at 7:43
  • @AmanMaurya so you need to sort by day and time, then merge dulicates by day and by time (sorting + two loops)? Commented Nov 28, 2017 at 7:59
  • @Neodan yes.... Commented Nov 28, 2017 at 8:16

1 Answer 1

1

There are 4 basic steps:

  1. Remove duplicate rows.
  2. Sort all rows by day (via lookup) ASC, then time (as a string) ASC.
  3. Store joined time values using day values as temporary keys.
  4. Store joined day values using joined time values as temporary keys.

Code: (Demo)

$array=[
    ['day'=>'Tuesday','time'=>'07:44 pm - 08:44 pm'],
    ['day'=>'Tuesday','time'=>'04:00 am - 04:25 am'],
    ['day'=>'Sunday','time'=>'04:00 am - 04:25 am'],
    ['day'=>'Sunday','time'=>'04:00 am - 04:25 am'],
    ['day'=>'Friday','time'=>'04:00 am - 04:25 am'],
    ['day'=>'Friday','time'=>'04:00 am - 04:25 am']
];

$array=array_unique($array,SORT_REGULAR);  // remove exact duplicate rows

$order=array_flip(['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday']);  // lookup array
usort($array,function($a,$b)use($order){  // sort by day name ASC then time ASC
    if($order[$a['day']]==$order[$b['day']]){
        return $a['time']<=>$b['time'];  // 2nd sort criteria: time string
    }
    return $order[$a['day']]<=>$order[$b['day']];  // 1st sort criteria: day name via lookup array
});

foreach($array as $row){
    if(!isset($temp[$row['day']])){
        $temp[$row['day']]=$row['time'];  // store time for first occurring day
    }else{
        $temp[$row['day']].=" & {$row['time']}";  // join times (for pre-existing day) as they are found
    }
}

foreach($temp as $day=>$times){
    if(!isset($result[$times])){
        $result[$times]=['day'=>$day,'time'=>$times];  // store first occurring day and time using time as temp key
    }else{
        $result[$times]['day'].=" & $day";  // join day names as they are found
    }
}
var_export(array_values($result)); // optionally remove the temporary keys

Output:

array (
  0 => 
  array (
    'day' => 'Tuesday',
    'time' => '04:00 am - 04:25 am & 07:44 pm - 08:44 pm',
  ),
  1 => 
  array (
    'day' => 'Friday & Sunday',
    'time' => '04:00 am - 04:25 am',
  ),
)

Here is another version that doesn't call array_unique(), but I don't like it as much because it does iterated sort() calls and generates a deeper temporary array.

foreach($array as $row){
    $temp[$row['day']][$row['time']]=$row['time'];  // remove duplicates and group by day
}

$order=array_flip(['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday']);  // lookup array
uksort($temp,function($a,$b)use($order){
    return $order[$a]<=>$order[$b];  // sort by day name via lookup array
});

foreach($temp as $day=>$times){
    sort($times);  // sort time elements ASC
    $time_key=implode(' & ',$times);  // join the day's time elements
    if(!isset($result[$time_key])){  // if first occurrence of the time string
        $result[$time_key]=['day'=>$day,'time'=>$time_key];  // store data using time string as temp key
    }else{
        $result[$time_key]['day'].=" & {$day}";  // concatenate new day to day element
    }
}

var_export(array_values($result));
Sign up to request clarification or add additional context in comments.

1 Comment

I this code only work on PHP version 7 or more..but this not the issue...thanx @mickmackusa

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.