Search code examples
javascriptarrayssemantic-versioning

Get array of latest minor versions from array


I have this array of semver versions:

let versions = ['4.5.0', '4.5.1', '4.5.2', '4.6.0', '4.6.1', '4.6.2', '4.7.0', '4.7.1', '4.8.0', '4.8.1']

I want to filter this array and keep only the latest patch versions based on minor and major versions.

Expected result:

['4.5.2', '4.6.2', '4.7.1', '4.8.1']

I tried to check every version in two loops comparing major and minor versions, but every time I have duplicates and lower versions in the final array.


My code:

for (let versions of supportedReleaseList) {
  for (let doubleCheckVersion of supportedReleaseList) {
    if (semver.parse(versions).major === semver.parse(doubleCheckVersion).major) {
      if (semver.parse(versions).minor === semver.parse(doubleCheckVersion).minor) {
        if (semver.parse(versions).patch > semver.parse(doubleCheckVersion).patch) {
           finalList.push(versions);
        }
      }
    }
  }
}

And the result was:

['4.5.1', '4.5.2', '4.5.2', '4.6.1', '4.6.2', '4.6.2', '4.7.1', '4.8.1']


Solution

  • I would do something like this. It will work regardless of whether the input list is ordered or not:

    const semver = require('semver');
    
    const versions = [
      '4.5.0', '4.5.1', '4.5.2',
      '4.6.0', '4.6.1', '4.6.2',
      '4.7.0', '4.7.1',
      '4.8.0', '4.8.1'
    ];
    
    const latestMinorVersions = new Map();
    
    for ( const v of versions.map( semver.parse ) ) {
        const baseVersion = new semver.SemVer(`${v.major}.${v.minor}.0`).toString();
    
        if ( !latestMinorVersions.has( baseVersion ) ) {
            latestMinorVersions.set( baseVersion, v );
        }
    
        const maxVersion = latestMinorVersions.get( baseVersion );
        const cc         = maxVersion.compare( v );
        if ( cc < 0 ) {
            latestMinorVersions.set(baseVersion, v);
        }
    
    }
    
    console.log(Array.from(latestMinorVersions.values()).map(v => v.toString()));
    

    It produces the desired ['4.5.2', '4.6.2', '4.7.1', '4.8.1'].

    Note that if your versions array contains prerelease and/or build metadata like 1.2.3-beta, 1.2.3+456, or 1.2.3.beta+456, this may not work as expected: I would recommend testing those edge cases.