Search code examples
phparraysloopsflatten

Merge one column from two 2d arrays and remove duplicates


I am running two queries, they return arrays similar to what is shown below:

First:

array(
    array(
        'id' => 1
    ),
    array(
        'id' => 2
    ),
    array(
        'id' => 3
    ),
    array(
        'id' => 4
    ),
)

Second:

array(
    array(
        'id' => 4
    ),
    array(
        'id' => 5
    ),
    array(
        'id' => 6
    ),
    array(
        'id' => 7
    ),
)

But I want to end up with

$ids = array(1,2,3,4,5,6,7);

But the only way I can think of to do that is

$ids = array();
foreach(array($array1, $array2) as $a){
    foreach($a as $id){
        $ids[] = $id['id'];
    }
}
$ids = array_unique($ids);

But that doesn't seem very efficient to me, and with the wealth of array functions out there, I am wondering if there is a better way?


Solution

  • There would be a few ways to handle this. I think I would probably start with array_merge() on the two original arrays, then flatten it with array_map(), and finally call array_unique().

    // Combine them
    $new = array_merge($array1, $array2);
    // Flatten them
    // array_map() is used to select the 'id' key from each
    $new = array_map(function($a) { 
      return $a['id'];
    }, $new);
    // And get the unique values
    $ids = array_unique($new);
    
    print_r($ids);
    Array
    (
        [0] => 1
        [1] => 2
        [2] => 3
        [3] => 4
        [5] => 5
        [6] => 6
        [7] => 7
    )
    

    Better: Do it in one query.

    After seeing the query, these do not need to be two arrays. It can be done with a single UNION query. Using a plain UNION instead of a UNION ALL will deduplicate them for you.

    SELECT
      game_id AS id
    FROM user_game 
    WHERE user_id = :userid
    UNION
    SELECT
      id
    FROM games
    WHERE referee_id = :userid OR reviewer_id = :userid
    ORDER BY id
    

    When fetching rows, since you have only one column, you may consider directly flattening it in the fetch.

    // For example
    while ($row = $stmt->fetch()) {
      // Pluck only the id from the row fetched
      $ids[] = $row['id'];
    }
    // $ids is now a 1D array.