skip to Main Content

There is an array of "movements" of elements, about the same, only it can be many times more:

Array
(
    [0] => Array
        (
            [id] => 90415
            [oldDate] => 2024-08-27
            [newDate] => 2024-08-28
        )

    [1] => Array
        (
            [id] => 90415
            [oldDate] => 2024-08-28
            [newDate] => 2024-08-27
        )

    [2] => Array
        (
            [id] => 90409
            [oldDate] => 2024-08-21
            [newDate] => 2024-08-22
        )

    [3] => Array
        (
            [id] => 90409
            [oldDate] => 2024-08-22
            [newDate] => 2024-08-23
        )
)

I’m trying to make sure that all the intermediate movements of the element are deleted, only the initial and final ones remain, and the elements of the array are deleted, where the element is returned to its original position (0 and 1 elements of the array). In the end, the processed array should look like this:

Array
(
    [0] => Array
        (
            [id] => 90409
            [oldDate] => 2024-08-21
            [newDate] => 2024-08-23
        )
)

how can I do this so that an array of a large number of elements does not delay the script for a long time

2

Answers


  1. Here is a solution that uses an intermediate $data associative array, which allows efficient lookups:

    $moves = [
        ['id' => 90415, 'oldDate' => '2024-08-27', 'newDate' => '2024-08-28'],
        ['id' => 90415, 'oldDate' => '2024-08-28', 'newDate' => '2024-08-27'],
        ['id' => 90409, 'oldDate' => '2024-08-21', 'newDate' => '2024-08-22'],
        ['id' => 90409, 'oldDate' => '2024-08-22', 'newDate' => '2024-08-23'],
        ];
    
    $data = [];
    foreach($moves as $move)
    {
        $id = $move['id'];
        if(isset($data[$id]))
        {
            // Id already present, update its newDate
            $data[$id]['newDate'] = $move['newDate'];
        }
        else
        {
            // New id, store it
            $data[$id] = $move;
        }
    }
    
    // Keep ids with different oldDate and newDate
    $result = array_filter($data, fn($move) => $move['oldDate'] != $move['newDate']);
    
    // Remove array keys
    $result = array_values($result);
    
    var_export($result);
    

    Output:

    array (
      0 => 
      array (
        'id' => 90409,
        'oldDate' => '2024-08-21',
        'newDate' => '2024-08-23',
      ),
    )
    
    Login or Signup to reply.
  2. Simply for comparison, here is the functional-style equivalent of Olivier’s (flawless) solution. Demo

    var_export(
        array_values(
            array_filter(
                array_reduce(
                    $movements,
                    function($carry, $move) {
                        $carry[$move['id']] ??= $move;
                        $carry[$move['id']]['newDate'] = $move['newDate'];
                        return $carry;
                    }
                ),
                fn($move) => $move['oldDate'] != $move['newDate']
            )
        )
    );
    

    It could also be written as: Demo

    $grouped = [];
    foreach ($movements as $move) {
        $grouped[$move['id']] ??= $move;                     // store if a new id
        $grouped[$move['id']]['newDate'] = $move['newDate']; // overwrite stored newDate
    }
    
    var_export(
        array_values(
            array_filter(
                $grouped,
                fn($move) => $move['oldDate'] != $move['newDate']
            )
        )
    );
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search