#2922 closed Feature Request (Completed)
Better reliability for _VersionCompare()
Reported by: | Synix <cross.fire@…> | Owned by: | Jpm |
---|---|---|---|
Milestone: | 3.3.13.20 | Component: | Standard UDFs |
Version: | Severity: | None | |
Keywords: | Cc: |
Description
In ticket #1881 someone stated that version comparing returns incorrect values in some cases. I also encountered these issues some times, so I wanted to suggest you to change the code to my following proposal:
Func _VersionCompare($sVersion1, $sVersion2) If $sVersion1 = $sVersion2 Then Return 0 Local $aVersion1 = StringSplit($sVersion1, ".,"), _ $aVersion2 = StringSplit($sVersion2, ".,") Local $iPartDifference = ($aVersion1[0] - $aVersion2[0]) If $iPartDifference < 0 Then ;$sVersion1 consists of less parts, fill the missing parts with zeros ReDim $aVersion1[UBound($aVersion2)] $aVersion1[0] = UBound($aVersion1) - 1 For $i = (UBound($aVersion1) - Abs($iPartDifference)) To $aVersion1[0] $aVersion1[$i] = "0" Next ElseIf $iPartDifference > 0 Then ;$sVersion2 consists of less parts, fill the missing parts with zeros ReDim $aVersion2[UBound($aVersion1)] $aVersion2[0] = UBound($aVersion2) - 1 For $i = (UBound($aVersion2) - Abs($iPartDifference)) To $aVersion2[0] $aVersion2[$i] = "0" Next EndIf For $i = 1 To $aVersion1[0] ; Compare this segment as numbers If StringIsDigit($aVersion1[$i]) And StringIsDigit($aVersion2[$i]) Then If Number($aVersion1[$i]) > Number($aVersion2[$i]) Then Return SetExtended(2, 1) ; @extended set to 2 for number comparison. ElseIf Number($aVersion1[$i]) < Number($aVersion2[$i]) Then Return SetExtended(2, -1) ; @extended set to 2 for number comparison. EndIf Else ; Compare the segment as strings If $aVersion1[$i] > $aVersion2[$i] Then Return SetExtended(1, 1) ; @extended set to 1 for string comparison. ElseIf $aVersion1[$i] < $aVersion2[$i] Then Return SetExtended(1, -1) ; @extended set to 1 for string comparison. EndIf EndIf Next ; This point should never be reached Return SetError(2, 0, 0) EndFunc ;==>_VersionCompare
This basically equals the "part length" for both versions before comparing, which leads to precise numerical comparisons (if both input versions are numerical). This eliminates all errors on numerical version compares with unequal part lentghs like _VersionCompare("1.2.1", "1.10").
When comparing versions with unequal part lengths, that have non-numerical parts at the end, it will eliminate incorrect return values in cases like _VersionCompare("1.11.1b", "1.2") for example.
Some thing to note though is, that this can not "fix" string comparisons like "1.1b" to "1.11c" for example, due to the nature of the lexicographical comparison.
Attachments (0)
Change History (4)
comment:1 Changed 10 years ago by TicketCleanup
- Version 3.3.12.0 deleted
comment:2 Changed 10 years ago by Jpm
Do you have objection if i change?
; Compare this segment as numbers If StringIsDigit(StringLeft($aVersion1[$i], 1)) And StringIsDigit(StringLeft($aVersion2[$i], 1)) Then
It can allow "1.1b" to "1.11c"
comment:3 Changed 10 years ago by Jpm
- Milestone set to 3.3.13.20
- Owner set to Jpm
- Resolution set to Completed
- Status changed from new to closed
Added by revision [11131] in version: 3.3.13.20
comment:4 Changed 10 years ago by Synix <cross.fire@…>
Nice idea :) thanks.
You could even go completely nuts and separate the numbers from letters using RegEx and compare each part after that, but that would be quite an overkill code-wise and most cases of version numbers will be covered with the coming update anyways.
Guidelines for posting comments:
- You cannot re-open a ticket but you may still leave a comment if you have additional information to add.
- In-depth discussions should take place on the forum.
For more information see the full version of the ticket guidelines here.
Automatic ticket cleanup.