2

I have this array

  Array
  (
    [0] => Array
        (
            [date] => 2020-10-07 10:49:48
            [content] => 1
        )
    [1] => Array
        (
            [date] => 2020-10-08 13:49:48
            [content] => 2
        )
    [2] => Array
        (
            [date] => 2020-10-08 13:50:03
            [content] => 3
        )
  )

I want to get:

  Array
  (
    [0] => Array
        (
            [date] => 2020-10-07 10:49:48
            [content] => 1
        )
    [1] => Array
        (
            [date] => 2020-10-08 13:50:03
            [content] => 2, 3
        )
  )

Like you see, if date between elements is less than hour (for example), content of both elements should be grouped with the greater date value. I just don't understand how to do it properly

I got this, but idk why i have extra element in array

        foreach ($result as $key => $value) {
            foreach ($result as $key2 => $value2) {
                if (abs(strtotime($value['date_added']) - strtotime($value2['date_added'])) <= 3600 && $key != $key2) {
                    $result[$key]['content'] = $value['content'] . ',' . $value2['content'];
                    unset($result[$key2]);
                }
            }
            $merged_array[] = $result[$key];
        }
8
  • you wanna mean date] => 2020-10-07 10:49:48 [content] => 1, 2 Commented Oct 8, 2020 at 14:59
  • 1 and 2 element have 1 minute difference, so they should be grouped Commented Oct 8, 2020 at 15:01
  • ok sorry, but you regroupe [content] => 2, 3, where is 3 ? and where is [date] => 2020-10-08 13:49:48 ? Commented Oct 8, 2020 at 15:07
  • 3 element should be removed of course and joined to 2. Commented Oct 8, 2020 at 15:10
  • do we need to check sequentially or in any order. Or what happens if 1st record is 7:00, 2nd is 7:50 and 3rd is 8:30. Should these be merged? Commented Oct 8, 2020 at 16:56

2 Answers 2

1

It is not clearly described which time differences should be used. The solution here always calculates the time differences to the highest date of the group.

The array will be sorted in descending order of the date. The highest date is set as $groupDate. A new $result array is created with a foreach loop. If the date difference to $groupDate is less than $intervalHour, then 'content' is accumulated. In the other case a new $groupDate is set. At the end the result array is sorted again according to increasing date.

$data = [
  ['date' => '2020-10-07 10:49:48', 'content' => 1],
  ['date' => '2020-10-08 13:49:48', 'content' => 2],
  ['date' => '2020-10-08 13:50:03', 'content' => 3],
  ['date' => '2020-10-08 14:50:04', 'content' => 4],
];

$intervalHour = 1.0;

usort($data,function($a,$b){return $b['date'] <=> $a['date'];});

$groupDate = date_create($data[0]['date']);
$content = $data[0]['content'];
$result = [$data[0]];
$k = 0;
foreach($data as $i => $row){
  if($i == 0) continue;
  $diff = date_create($row['date'])->diff($groupDate);
  $diffHour = $diff->days * 24 + $diff->h + $diff->i/60 + $diff->s/3600;  
  if($diffHour < $intervalHour) {
    $content = $row['content'].','.$content;
  }
  else {
    ++$k;
    $groupDate = date_create($row['date']);
    $result[$k]['date'] = $groupDate->format('Y-m-d H:i:s');
    $content = $row['content'];
  }
  $result[$k]['content'] = $content;
}

usort($result,function($a,$b){return $a['date'] <=> $b['date'];});

echo '<pre>',var_export($result);

Output with $intervalHour = 1.0

array (
  0 => 
  array (
    'date' => '2020-10-07 10:49:48',
    'content' => 1,
  ),
  1 => 
  array (
    'date' => '2020-10-08 13:50:03',
    'content' => '2,3',
  ),
  2 => 
  array (
    'date' => '2020-10-08 14:50:04',
    'content' => 4,
  ),
) 

Output with $intervalHour = 2.0

array (
  0 => 
  array (
    'date' => '2020-10-07 10:49:48',
    'content' => 1,
  ),
  1 => 
  array (
    'date' => '2020-10-08 14:50:04',
    'content' => '2,3,4',
  ),
) 
Sign up to request clarification or add additional context in comments.

Comments

0

The problem is that your unset command does not work. When you use a foreach on an array, a copy of that array will be created and iterated. If you want to iterate over an instance that you can change on the fly, you would need to pass an iterable object.

As an example, the following would output 12, despite the unset:

$x = [1, 2];

foreach ($x as $key => $value) {
    echo $value;
    unset($x[1]);
}

I think best approach is using OOP. But if you want to work only with forloops and arrays, it could be done like this:

  $usedKeys = [];
  $dateContent  =[];

  foreach ($result as $key => $value) {
      if (in_array($key, $usedKeys)) {
          continue;
      }
      $usedKeys[] = $key;
      $dateContent[$key]['content'] = [$value['content']];
      foreach ($result as $key2 => $value2) {
          if (in_array($key2, $usedKeys)) {
              continue;
          }

          if (abs(strtotime($value['date']) - strtotime($value2['date'])) <= 3600 && $key != $key2) {
              $dateContent[$key]['content'][] = $value2['content'];
              $usedKeys[] = $key2;
          }
      }
  }

  $dateContent = array_map(function ($value) {
      return implode(',', $value['content']);
  }, $dateContent);

Comments

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.