1

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>&nbsp;</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?

0

2 Answers 2

1

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>&nbsp;</td>";
                } else {
                    $class = $lookup[$date] > 1 ? ' class="text-danger"' : '';
                    $result .= "\n\t<td$class>$date</td>";
                }
                return $result;
            },
            ''
        )
    );
}
if ($html) {
    printf($table, $html);
}
Sign up to request clarification or add additional context in comments.

Comments

1

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);

6 Comments

I checked your code, but it dosen't work as I needed. That mean it not identifying all duplicate dates. Here I want to highlight text in red for all the duplicate dates.
I made a small update in the code. If you run it, it says 2022-09-02 is double! 2022-09-04 is double! 2022-09-08 is double! And in fact, these are the three duplicate dates in the Array. That's what you wanted to get.
Yes, your solution is almost correct. But it can not get the duplicate date in this array 1 => array ( 'title' => 'Title 01', 'dates' => array ( 2 => '2022-09-08', 13 => '2022-08-17', 14 => '2022-09-02', ), ),
It comes from the first element of my original array.
Ah I see. Check the corrected version. It dumps an array with all duplicates and the corresponding array keys of both the outer and inner arrays
|

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.