Search code examples
phparraysmaxfilteringversion

Filter rows containing modules and software version values and retain unique modules with highest version


I have an array like this :

Array (
    [vendor] => Array (
        [0] => Array ( [name] => module-one [version] => 1.7.0 )
        [1] => Array ( [name] => module-one [version] => 1.8.0 )
        [2] => Array ( [name] => module-two [version] => 1.8.0 )
        [3] => Array ( [name] => module-two [version] => 1.2.0 )
        [4] => Array ( [name] => module-three [version] => 1.9.0 )
        [5] => Array ( [name] => module-three [version] => 1.8.0 )
    )
)

I would like to compare the array by the key name and if it's a match get the highest version available like this :

Array (
    [vendor] => Array (
        [0] => Array ( [name] => module-one [version] => 1.8.0 )
        [1] => Array ( [name] => module-two [version] => 1.8.0 )
        [2] => Array ( [name] => module-three [version] => 1.9.0 )
    )
)

Solution

  • PHP has a native version comparison function that makes this job very simple. Group by the name values and when you encounter any subsequent rows that match a particular group -- only save the new row if the version is greater.

    I've altered your sample input to indicate that multi-digit version values will be treated correctly.

    Code: (Demo)

    $vendor = [
        [ "name" => "module-one", "version" => "1.7.0" ],
        [ "name" => "module-one", "version" => "1.8.0" ],
        [ "name" => "module-two", "version" => "1.8.0" ],
        [ "name" => "module-two", "version" => "1.12.0" ],
        [ "name" => "module-three", "version" => "1.9.0" ],
        [ "name" => "module-three", "version" => "1.8.0" ],
    ];
    
    $result = [];
    foreach ($vendor as $row) {
        if (
            !isset($result[$row['name']])
            || version_compare($result[$row['name']]['version'], $row['version'], '<')
        ) {
            $result[$row['name']] = $row;
        }
    }
    var_export(array_values($result));
    

    Output:

    array (
      0 => 
      array (
        'name' => 'module-one',
        'version' => '1.8.0',
      ),
      1 => 
      array (
        'name' => 'module-two',
        'version' => '1.12.0',
      ),
      2 => 
      array (
        'name' => 'module-three',
        'version' => '1.9.0',
      ),
    )