Reputation: 715
I am refactoring a calendar app. The calendar has a user-defined grid (slots where bookings can occur), but needs to display "off-the-grid" bookings as well. Think of "regular" slots at 08:00, 09:00 and "irregular" slots when someone is booked at 08:39. For business reasons, I need to display these slots differently (CSS), otherwise they behave the same. I've searched the PHP Manual, but the built-in array functions don't do exactly what I need.
$officialGrid = [
['grid' => TRUE, 'time' => '08:00', 'content' => NULL],
['grid' => TRUE, 'time' => '09:00', 'content' => NULL],
];
$bookings = [
['grid' => NULL, 'time' => '08:00', 'content' => 'Paul Simon'],
['grid' => NULL, 'time' => '08:00', 'content' => 'Art Garfunkel'],
['grid' => NULL, 'time' => '08:39', 'content' => 'Homer J. Simpson'],
];
I could just append these arrays, but for performance reasons would like shorten the result to:
$timeSlotsToDisplay = [
['grid' => TRUE, 'time' => '08:00', 'content' => 'Paul Simon, Art Garfunkel'], //regular
['grid' => NULL, 'time' => '08:39', 'content' => 'Homer J. Simpson'], //irregular
['grid' => TRUE, 'time' => '09:00', 'content' => NULL], //vacant
];
I'm also flexible to change data types for the values (content
might be an array). Is there any elegant solution for merging these arrays, other than start looping and comparing?
PS: Just to illustrate, in PostgreSQL terms, I need to SELECT DISTINCT ON (time) grid, time, string_agg(content) FROM myDB GROUP BY time ORDER BY time, grid;
(please ignore possible keywords, not quoting due to formatting, also haven't tested the query).
Upvotes: 1
Views: 73
Reputation: 47904
$officialGrid
, this will serve as the base data for the result array.$bookings
array.$content
column value in the result array with a conditional comma&space then the new row's content
value.array_values()
.Code: (Demo)
$result = array_column($officialGrid, null, 'time');
foreach ($bookings as $row) {
if (!isset($result[$row['time']])) {
$result[$row['time']] = $row;
} else {
$result[$row['time']]['content'] = sprintf(
'%s%s',
(isset($result[$row['time']]['content']) ? "{$result[$row['time']]['content']}, " : ''),
$row['content']
);
}
}
ksort($result);
var_export(array_values($result));
Upvotes: 0
Reputation: 16214
I see nothing wrong with the loops.. but I suggest another structure for the $officialGrid
array
$officialGrid = array(
'08:00' => array('grid' => TRUE, 'content' => NULL),
'09:00' => array('grid' => TRUE, 'content' => NULL));
$bookings = array(
array('grid' => NULL, 'time' => '08:00', 'content' => 'Paul Simon'),
array('grid' => NULL, 'time' => '08:00', 'content' => 'Art Garfunkel'),
array('grid' => NULL, 'time' => '08:39', 'content' => 'Homer J. Simpson'));
$timeSlotsToDisplay = $officialGrid;
array_map(function($el) use(&$timeSlotsToDisplay, $officialGrid) {
$timeSlotsToDisplay[$el['time']] = array(
'content' =>
(isset($timeSlotsToDisplay[$el['time']]) ?
trim($timeSlotsToDisplay[$el['time']]['content'], ',') . ',' : '') .
$el['content'],
'grid' => isset($officialGrid[$el['time']]) ? true : null
);
}, $bookings);
ksort($timeSlotsToDisplay);
var_dump($timeSlotsToDisplay);
array_map
can be replaced by a single foreach
loop.
Upvotes: 1