简体   繁体   中英

Group array rows by year and month of date value and push a column value into the group

I have an array of events containing a title, start time, end time, start date.

I'm looping through all of the results currently with:

foreach ($events as $event) {
    echo $event['title'];
}

Which lists the items absolutely fine.

Is there a way I can GROUP the below array into months per year? Eg.

May 2018

  • Title 2
  • Title 3

July 2018

  • Title 3

January 2019

  • Title 4

My sample input rows:

Array
(
    [title] => Title 1
    [start_time] => 09:00
    [end_time] => 17:00
    [start_date] => 2017-05-25
)


Array
(
    [title] => Title 2
    [start_time] => 09:00
    [end_time] => 17:00
    [start_date] => 2018-05-25
)

                        
Array
(
    [title] => Title 3
    [start_time] => 09:00
    [end_time] => 17:00
    [start_date] => 2018-05-27
)


Array
(
    [title] => Title 3
    [start_time] => 09:00
    [end_time] => 17:00
    [start_date] => 2018-07-15
)

Array
(
    [title] => Title 4
    [start_time] => 09:00
    [end_time] => 17:00
    [start_date] => 2019-01-2
)

Something as per code below should work. You will have to group them by year, and month and then sort them desc

$dates = [];
foreach($arrayOfDates as $event){
   $timestamp = strtotime($event['start_date']);
   $dateSort = date('Y-m', $timestamp);
   $dates[$dateSort][] = ['title' => $event['title']];
}

krsort($dates);
foreach($dates as $key => $values){
   echo $key;
   foreach($values as $value){
      echo "* ". $value['title'];
   }   
}

Writing out JoshKisb's suggestion:

$monGrp = array();

// build an array based on YYYY-MM since that is what we're grouping by
foreach ($events as $event) {
  $monGrp[substr($event['start_date'], 0, 7) . '-01'][] = $event;
}

// sort by the key so it is the correct date order
ksort($monGrp);

// now loop through the grouped array and write the desired output
foreach ($monGrp as $mon => $grpEvents) {

  echo "<p>" . date("F Y", strtotime($mon));

  foreach ($grpEvents as $event) {
    echo " - " . $event['title'] . "<br>\n";
  }

}

Certainly! First you need to make sure your array is sorted properly. Which it's best to use PHP's usort function for this. It accepts the array to sort and a function for which to compare the elements.

usort($array, function ($a, $b) {
    $aDate = strtotime($a['start_date']);
    $bDate = strtotime($b['start_date']);
    if ($aDate == $bDate) {
        return 0;
    }
    return ($aDate < $bDate) ? -1 : 1;
});

More on usort can be found here .

Once the array is properly sorted, then you can start to create sections in your code. A simple way to handle this is to create a variable that will track the section that you want to create. And when the section changes then it will output it in the loop. Obviously this only works if you have previously sorted the array, which was why I included the previous section.

$month = null;
foreach ($events as $event) {
    $newMonth = date('F', strtotime($event['start_date']) );
    if($month != $newMonth) {
        $month = $newMonth;
        echo $month;
    }
    echo $event['title'];
}

A couple of other function references ( strtotime , date ).

One possible way to achieve what you want consists of the following steps:

  • create an associative array to store the data.
  • iterate over every event, format the date and insert it in the array along with the titles.
  • iterate over the created array and its subarrays to print the desired result.

Code:

/* ----- Group the data ----- */

# Create an array to store the data.
$grouped = [];

# Iterate over every event.
foreach ($events as $event) {
    # Format and save the date as 'Month Year'.
    $monthYear = date("F Y", strtotime($event["start_date"]));

    # Define the key of the object as as an array, if not already defined.
    $grouped[$monthYear] = $grouped[$monthYear] ?? [];

    # Insert the title to the array corresponding to the formatted date.
    $grouped[$monthYear][] = $event["title"];
}

/* ----- Print the data ----- */

# Iterate over every key - value.
foreach ($grouped as $key => $value) {
    # Print the 'Month Year' key.
    echo $key . "\n";

    # Iterate over every title and print it.
    foreach ($value as $title) echo "- $title\n";

    # Separate each group with an empty line.
    echo "\n";
}

Example:

Check out this example for a live demonstration.


Note:

The line $grouped[$monthYear] = $grouped[$monthYear] ?? [] $grouped[$monthYear] = $grouped[$monthYear] ?? [] works for PHP7+ . If you use an older version, you can supplant it with the following:

# Check whether the key is not set.
if (!isset($grouped[$monthYear])) $grouped[$monthYear] = [];

Use one simple loop to group and push titles into each group, and another loop to print your formatted text.

Code: ( Demo )

$result = [];
foreach ($array as $row) {
    $key = date('F Y', strtotime($row['start_date']));
    $result[$key][] = $row['title'];
}

foreach ($result as $FY => $titles) {
    printf("%s\n- %s\n\n", $FY, implode("\n- ", $titles));
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM