Reputation: 115
Look at the array shown below:
$eData = array (
1 =>
array (
'title' => 'Title 01',
'dates' =>
array (
2 => '2022-09-08',
13 => '2022-08-17',
14 => '2022-09-02',
),
),
3 =>
array (
'title' => 'Title 02',
'dates' =>
array (
2 => '2022-09-09',
13 => '2022-09-02',
14 => '2022-09-04',
),
),
4 =>
array (
'title' => 'Title 03',
'dates' =>
array (
2 => '2022-09-12',
13 => '2022-09-03',
14 => '2022-09-22',
),
),
5 =>
array (
'title' => 'Title 04',
'dates' =>
array (
2 => NULL,
13 => '2022-09-04',
14 => NULL,
),
),
6 =>
array (
'title' => 'Title 05',
'dates' =>
array (
2 => '2022-09-23',
13 => '2022-09-05',
14 => NULL,
),
),
7 =>
array (
'title' => 'Title 06',
'dates' =>
array (
2 => NULL,
13 => '2022-09-06',
14 => NULL,
),
),
8 =>
array (
'title' => 'Title 07',
'dates' =>
array (
2 => NULL,
13 => NULL,
14 => NULL,
),
),
9 =>
array (
'title' => 'Title 08',
'dates' =>
array (
2 => '2022-10-07',
13 => '2022-09-08',
14 => NULL,
),
),
)
Here I need to identify duplicate dates in nested dates
array when it loop with foreach
.
This is how I tried it in php:
$i=1;
$tdata = $e_des = $prevDate = $dateDup = '';
foreach ($eData as $eid => $eventData) {
$e_title = $eventData['title'];
$tdata .= "<tr>
<td>{$i}</td>
<td>
<span>{$e_title}</span>
</td>";
foreach ($eventData['dates'] as $pid => $date) {
if ($date) {
$dateDup = $prevDate == $date ? ' text-danger' : '';
$tdata .= "<td class='$dateDup'>$date</td>";
} else {
$tdata .= "<td> </td>";
}
}
$tdata .= "</tr>";
$prevDate = $date;
$i++;
}
This is only identifying one duplicate date and it is,
[3] => Array
(
[title] => Title 02
[dates] => Array
(
[13] => 2022-09-02
)
)
But, in my array, you can see there are four duplicate values (2022-09-02, 2022-09-04).
Can anybody help me, How to modify my code to identify all four duplicates in my array?
Upvotes: 1
Views: 70
Reputation: 47894
Create a lookup array by collecting all dates, removing nulls, then counting occurrences with:
$lookup = array_count_values(array_filter(array_merge(...array_column($eData, 'dates'))));
Then while looping over your dates, check if the given date has occurred more than once.
$class = $lookup[$date] > 1 ? ' class="text-danger"' : '';
Here is my full re-scripting of your code:
Code: (Demo -- click on the eye icon to see the rendered HTML)
$lookup = array_count_values(array_filter(array_merge(...array_column($eData, 'dates'))));
$table = <<<HTML
<style> .text-danger { background-color: red; } </style>
<table border="1">
%s</table>
HTML;
$rowTemplate = <<<HTML
<tr>
<td>%d</td>
<td>
<span>%s</span>
</td>%s
</tr>
HTML;
$i = 1;
$html = '';
foreach ($eData as $id => $row) {
$html .= sprintf(
$rowTemplate,
++$i,
$row['title'],
array_reduce(
$row['dates'],
function ($result, $date) use($lookup) {
if (!$date) {
$result .= "\n\t<td> </td>";
} else {
$class = $lookup[$date] > 1 ? ' class="text-danger"' : '';
$result .= "\n\t<td$class>$date</td>";
}
return $result;
},
''
)
);
}
if ($html) {
printf($table, $html);
}
Upvotes: 1
Reputation: 185
Try this one:
$i = 1;
$existingDates = [];
$duplicates = [];
$tdata = $e_des = $prevDate = $dateDup = '';
foreach ($eData as $eid => $eventData) {
foreach ($eventData['dates'] as $pid => $date) {
if (!$date) {
continue;
}
if (!isset($duplicates[$date])) {
$duplicates[$date] = [];
}
$duplicates[$date][] = [$eid, $pid];
}
}
foreach ($duplicates as $date=>$possibleDuplicates) {
if(count($possibleDuplicates)<2) {
unset($duplicates[$date]);
}
}
var_dump($duplicates);
Upvotes: 1