How to compare two version number strings in golang

huangapple go评论117阅读模式
英文:

How to compare two version number strings in golang

问题

在Go语言中,你可以使用strings.Split函数将版本号字符串拆分为数字部分,然后逐个比较数字的大小来确定哪个版本号更大。下面是一个示例代码:

  1. package main
  2. import (
  3. "fmt"
  4. "strconv"
  5. "strings"
  6. )
  7. func compareVersions(a, b string) int {
  8. // 将版本号字符串拆分为数字部分
  9. aParts := strings.Split(a, ".")
  10. bParts := strings.Split(b, ".")
  11. // 比较每个数字部分的大小
  12. for i := 0; i < len(aParts) && i < len(bParts); i++ {
  13. aNum, _ := strconv.Atoi(aParts[i])
  14. bNum, _ := strconv.Atoi(bParts[i])
  15. if aNum < bNum {
  16. return -1
  17. } else if aNum > bNum {
  18. return 1
  19. }
  20. }
  21. // 如果前面的数字部分都相等,则比较版本号长度
  22. if len(aParts) < len(bParts) {
  23. return -1
  24. } else if len(aParts) > len(bParts) {
  25. return 1
  26. }
  27. // 版本号完全相等
  28. return 0
  29. }
  30. func main() {
  31. a := "1.05.00.0156"
  32. b := "1.0.221.9289"
  33. result := compareVersions(a, b)
  34. if result < 0 {
  35. fmt.Println("Version a is smaller")
  36. } else if result > 0 {
  37. fmt.Println("Version a is larger")
  38. } else {
  39. fmt.Println("Versions are equal")
  40. }
  41. }

这段代码定义了一个compareVersions函数,它接受两个版本号字符串作为参数,并返回一个整数来表示它们的大小关系。在main函数中,我们调用compareVersions函数来比较版本号ab,并根据比较结果输出相应的信息。

注意:这段代码假设版本号字符串的格式是正确的,即由数字和点号组成。如果版本号字符串的格式不正确,可能会导致错误。你可以根据实际情况添加错误处理逻辑。

英文:

I have two strings (they are actually version numbers and they could be any version numbers)

  1. a := &quot;1.05.00.0156&quot;
  2. b := &quot;1.0.221.9289&quot;

I want to compare which one is bigger. How to do it in golang?

答案1

得分: 29

有一个来自Hashicorp的不错的解决方案-https://github.com/hashicorp/go-version

  1. import github.com/hashicorp/go-version
  2. v1, err := version.NewVersion("1.2")
  3. v2, err := version.NewVersion("1.5+metadata")
  4. // 比较示例。还有GreaterThan、Equal和一个简单的Compare,返回一个int,可以轻松实现>=、<=等。
  5. if v1.LessThan(v2) {
  6. fmt.Printf("%s 小于 %s", v1, v2)
  7. }
英文:

There is a nice solution from Hashicorp - https://github.com/hashicorp/go-version

  1. import github.com/hashicorp/go-version
  2. v1, err := version.NewVersion(&quot;1.2&quot;)
  3. v2, err := version.NewVersion(&quot;1.5+metadata&quot;)
  4. // Comparison example. There is also GreaterThan, Equal, and just
  5. // a simple Compare that returns an int allowing easy &gt;=, &lt;=, etc.
  6. if v1.LessThan(v2) {
  7. fmt.Printf(&quot;%s is less than %s&quot;, v1, v2)
  8. }

答案2

得分: 13

前段时间我创建了一个版本比较库:https://github.com/mcuadros/go-version

  1. version.CompareSimple("1.05.00.0156", "1.0.221.9289")
  2. //返回:1

希望你喜欢!

英文:

Some time ago I created a version comparison library: https://github.com/mcuadros/go-version

  1. version.CompareSimple(&quot;1.05.00.0156&quot;, &quot;1.0.221.9289&quot;)
  2. //Returns: 1

Enjoy it!

答案3

得分: 9

这是一个通用解决方案。

  1. package main
  2. import "fmt"
  3. func VersionOrdinal(version string) string {
  4. // ISO/IEC 14651:2011
  5. const maxByte = 1<<8 - 1
  6. vo := make([]byte, 0, len(version)+8)
  7. j := -1
  8. for i := 0; i < len(version); i++ {
  9. b := version[i]
  10. if '0' > b || b > '9' {
  11. vo = append(vo, b)
  12. j = -1
  13. continue
  14. }
  15. if j == -1 {
  16. vo = append(vo, 0x00)
  17. j = len(vo) - 1
  18. }
  19. if vo[j] == 1 && vo[j+1] == '0' {
  20. vo[j+1] = b
  21. continue
  22. }
  23. if vo[j]+1 > maxByte {
  24. panic("VersionOrdinal: invalid version")
  25. }
  26. vo = append(vo, b)
  27. vo[j]++
  28. }
  29. return string(vo)
  30. }
  31. func main() {
  32. versions := []struct{ a, b string }{
  33. {"1.05.00.0156", "1.0.221.9289"},
  34. // Go versions
  35. {"1", "1.0.1"},
  36. {"1.0.1", "1.0.2"},
  37. {"1.0.2", "1.0.3"},
  38. {"1.0.3", "1.1"},
  39. {"1.1", "1.1.1"},
  40. {"1.1.1", "1.1.2"},
  41. {"1.1.2", "1.2"},
  42. }
  43. for _, version := range versions {
  44. a, b := VersionOrdinal(version.a), VersionOrdinal(version.b)
  45. switch {
  46. case a > b:
  47. fmt.Println(version.a, ">", version.b)
  48. case a < b:
  49. fmt.Println(version.a, "<", version.b)
  50. case a == b:
  51. fmt.Println(version.a, "=", version.b)
  52. }
  53. }
  54. }

输出:

  1. 1.05.00.0156 > 1.0.221.9289
  2. 1 < 1.0.1
  3. 1.0.1 < 1.0.2
  4. 1.0.2 < 1.0.3
  5. 1.0.3 < 1.1
  6. 1.1 < 1.1.1
  7. 1.1.1 < 1.1.2
  8. 1.1.2 < 1.2
英文:

Here's a general solution.

  1. package main
  2. import &quot;fmt&quot;
  3. func VersionOrdinal(version string) string {
  4. // ISO/IEC 14651:2011
  5. const maxByte = 1&lt;&lt;8 - 1
  6. vo := make([]byte, 0, len(version)+8)
  7. j := -1
  8. for i := 0; i &lt; len(version); i++ {
  9. b := version[i]
  10. if &#39;0&#39; &gt; b || b &gt; &#39;9&#39; {
  11. vo = append(vo, b)
  12. j = -1
  13. continue
  14. }
  15. if j == -1 {
  16. vo = append(vo, 0x00)
  17. j = len(vo) - 1
  18. }
  19. if vo[j] == 1 &amp;&amp; vo[j+1] == &#39;0&#39; {
  20. vo[j+1] = b
  21. continue
  22. }
  23. if vo[j]+1 &gt; maxByte {
  24. panic(&quot;VersionOrdinal: invalid version&quot;)
  25. }
  26. vo = append(vo, b)
  27. vo[j]++
  28. }
  29. return string(vo)
  30. }
  31. func main() {
  32. versions := []struct{ a, b string }{
  33. {&quot;1.05.00.0156&quot;, &quot;1.0.221.9289&quot;},
  34. // Go versions
  35. {&quot;1&quot;, &quot;1.0.1&quot;},
  36. {&quot;1.0.1&quot;, &quot;1.0.2&quot;},
  37. {&quot;1.0.2&quot;, &quot;1.0.3&quot;},
  38. {&quot;1.0.3&quot;, &quot;1.1&quot;},
  39. {&quot;1.1&quot;, &quot;1.1.1&quot;},
  40. {&quot;1.1.1&quot;, &quot;1.1.2&quot;},
  41. {&quot;1.1.2&quot;, &quot;1.2&quot;},
  42. }
  43. for _, version := range versions {
  44. a, b := VersionOrdinal(version.a), VersionOrdinal(version.b)
  45. switch {
  46. case a &gt; b:
  47. fmt.Println(version.a, &quot;&gt;&quot;, version.b)
  48. case a &lt; b:
  49. fmt.Println(version.a, &quot;&lt;&quot;, version.b)
  50. case a == b:
  51. fmt.Println(version.a, &quot;=&quot;, version.b)
  52. }
  53. }
  54. }

Output:

  1. 1.05.00.0156 &gt; 1.0.221.9289
  2. 1 &lt; 1.0.1
  3. 1.0.1 &lt; 1.0.2
  4. 1.0.2 &lt; 1.0.3
  5. 1.0.3 &lt; 1.1
  6. 1.1 &lt; 1.1.1
  7. 1.1.1 &lt; 1.1.2
  8. 1.1.2 &lt; 1.2

答案4

得分: 4

go-semver 是一个用于 Go 语言的语义化版本库。它可以解析和比较两个语义化版本字符串。

示例:

  1. vA := semver.New("1.2.3")
  2. vB := semver.New("3.2.1")
  3. fmt.Printf("%s < %s == %t\n", vA, vB, vA.LessThan(*vB))

输出:

1.2.3 < 3.2.1 == true

英文:

go-semver is a semantic versioning library for Go. It lets you parse and compare two semantic version strings.

Example:

  1. vA := semver.New(&quot;1.2.3&quot;)
  2. vB := semver.New(&quot;3.2.1&quot;)
  3. fmt.Printf(&quot;%s &lt; %s == %t\n&quot;, vA, vB, vA.LessThan(*vB))

Output:

> 1.2.3 < 3.2.1 == true

答案5

得分: 4

以下是版本比较的一些库:

  1. https://github.com/blang/semver
  2. https://github.com/Masterminds/semver
  3. https://github.com/hashicorp/go-version
  4. https://github.com/mcuadros/go-version

我使用了blang/semver库。
例如:https://play.golang.org/p/1zZvEjLSOAr

  1. import github.com/blang/semver/v4
  2. v1, err := semver.Make("1.0.0-beta")
  3. v2, err := semver.Make("2.0.0-beta")
  4. // 可用选项
  5. v1.Compare(v2) // 比较
  6. v1.LT(v2) // 小于
  7. v1.GT(v2) // 大于
英文:

Here are some of the libraries for version comparison:

  1. https://github.com/blang/semver
  2. https://github.com/Masterminds/semver
  3. https://github.com/hashicorp/go-version
  4. https://github.com/mcuadros/go-version

I have used blang/semver.
Eg: https://play.golang.org/p/1zZvEjLSOAr

<!-- language: lang-go -->

  1. import github.com/blang/semver/v4
  2. v1, err := semver.Make(&quot;1.0.0-beta&quot;)
  3. v2, err := semver.Make(&quot;2.0.0-beta&quot;)
  4. // Options availabe
  5. v1.Compare(v2) // Compare
  6. v1.LT(v2) // LessThan
  7. v1.GT(v2) // GreaterThan

答案6

得分: 2

这取决于你对"bigger"的理解。

一个简单的方法是:

  1. package main
  2. import "fmt"
  3. import "strings"
  4. func main() {
  5. a := strings.Split("1.05.00.0156", ".")
  6. b := strings.Split("1.0.221.9289", ".")
  7. for i, s := range a {
  8. var ai, bi int
  9. fmt.Sscanf(s, "%d", &ai)
  10. fmt.Sscanf(b[i], "%d", &bi)
  11. if ai > bi {
  12. fmt.Printf("%v 比 %v 大\n", a, b)
  13. break
  14. }
  15. if bi > ai {
  16. fmt.Printf("%v 比 %v 大\n", b, a)
  17. break
  18. }
  19. }
  20. }

你可以在这里运行这段代码:http://play.golang.org/p/j0MtFcn44Z

英文:

This depends on what you mean by bigger.

A naive approach would be:

  1. package main
  2. import &quot;fmt&quot;
  3. import &quot;strings&quot;
  4. func main() {
  5. a := strings.Split(&quot;1.05.00.0156&quot;, &quot;.&quot;)
  6. b := strings.Split(&quot;1.0.221.9289&quot;, &quot;.&quot;)
  7. for i, s := range a {
  8. var ai, bi int
  9. fmt.Sscanf(s, &quot;%d&quot;, &amp;ai)
  10. fmt.Sscanf(b[i], &quot;%d&quot;, &amp;bi)
  11. if ai &gt; bi {
  12. fmt.Printf(&quot;%v is bigger than %v\n&quot;, a, b)
  13. break
  14. }
  15. if bi &gt; ai {
  16. fmt.Printf(&quot;%v is bigger than %v\n&quot;, b, a)
  17. break
  18. }
  19. }
  20. }

http://play.golang.org/p/j0MtFcn44Z

答案7

得分: 2

根据Jeremy Wall的回答:

  1. func compareVer(a, b string) (ret int) {
  2. as := strings.Split(a, ".")
  3. bs := strings.Split(b, ".")
  4. loopMax := len(bs)
  5. if len(as) > len(bs) {
  6. loopMax = len(as)
  7. }
  8. for i := 0; i < loopMax; i++ {
  9. var x, y string
  10. if len(as) > i {
  11. x = as[i]
  12. }
  13. if len(bs) > i {
  14. y = bs[i]
  15. }
  16. xi,_ := strconv.Atoi(x)
  17. yi,_ := strconv.Atoi(y)
  18. if xi > yi {
  19. ret = -1
  20. } else if xi < yi {
  21. ret = 1
  22. }
  23. if ret != 0 {
  24. break
  25. }
  26. }
  27. return
  28. }

点击此处查看代码。

英文:

Based on Jeremy Wall's answer:

  1. func compareVer(a, b string) (ret int) {
  2. as := strings.Split(a, &quot;.&quot;)
  3. bs := strings.Split(b, &quot;.&quot;)
  4. loopMax := len(bs)
  5. if len(as) &gt; len(bs) {
  6. loopMax = len(as)
  7. }
  8. for i := 0; i &lt; loopMax; i++ {
  9. var x, y string
  10. if len(as) &gt; i {
  11. x = as[i]
  12. }
  13. if len(bs) &gt; i {
  14. y = bs[i]
  15. }
  16. xi,_ := strconv.Atoi(x)
  17. yi,_ := strconv.Atoi(y)
  18. if xi &gt; yi {
  19. ret = -1
  20. } else if xi &lt; yi {
  21. ret = 1
  22. }
  23. if ret != 0 {
  24. break
  25. }
  26. }
  27. return
  28. }

http://play.golang.org/p/AetJqvFc3B

答案8

得分: 1

追求清晰和简洁:

  1. func intVer(v string) (int64, error) {
  2. sections := strings.Split(v, ".")
  3. intVerSection := func(v string, n int) string {
  4. if n < len(sections) {
  5. return fmt.Sprintf("%04s", sections[n])
  6. } else {
  7. return "0000"
  8. }
  9. }
  10. s := ""
  11. for i := 0; i < 4; i++ {
  12. s += intVerSection(v, i)
  13. }
  14. return strconv.ParseInt(s, 10, 64)
  15. }
  16. func main() {
  17. a := "3.045.98.0832"
  18. b := "087.2345"
  19. va, _ := intVer(a)
  20. vb, _ := intVer(b)
  21. fmt.Println(va<vb)
  22. }

比较版本意味着需要解析,所以我认为这两个步骤应该分开进行,以提高鲁棒性。

英文:

Striving for clarity and simplicity:

  1. func intVer(v string) (int64, error) {
  2. sections := strings.Split(v, &quot;.&quot;)
  3. intVerSection := func(v string, n int) string {
  4. if n &lt; len(sections) {
  5. return fmt.Sprintf(&quot;%04s&quot;, sections[n])
  6. } else {
  7. return &quot;0000&quot;
  8. }
  9. }
  10. s := &quot;&quot;
  11. for i := 0; i &lt; 4; i++ {
  12. s += intVerSection(v, i)
  13. }
  14. return strconv.ParseInt(s, 10, 64)
  15. }
  16. func main() {
  17. a := &quot;3.045.98.0832&quot;
  18. b := &quot;087.2345&quot;
  19. va, _ := intVer(a)
  20. vb, _ := intVer(b)
  21. fmt.Println(va&lt;vb)
  22. }

Comparing versions implies parsing so I believe these 2 steps should be separate to make it robust.

答案9

得分: 1

在leetcode上进行了测试:https://leetcode.com/problems/compare-version-numbers/

  1. func compareVersion(version1 string, version2 string) int {
  2. len1, len2, i, j := len(version1), len(version2), 0, 0
  3. for i < len1 || j < len2 {
  4. n1 := 0
  5. for i < len1 && '0' <= version1[i] && version1[i] <= '9' {
  6. n1 = n1 * 10 + int(version1[i] - '0')
  7. i++
  8. }
  9. n2 := 0
  10. for j < len2 && '0' <= version2[j] && version2[j] <= '9' {
  11. n2 = n2 * 10 + int(version2[j] - '0')
  12. j++
  13. }
  14. if n1 > n2 {
  15. return 1
  16. }
  17. if n1 < n2 {
  18. return -1
  19. }
  20. i, j = i+1, j+1
  21. }
  22. return 0
  23. }
英文:

tested in leetcode: https://leetcode.com/problems/compare-version-numbers/

  1. func compareVersion(version1 string, version2 string) int {
  2. len1, len2, i, j := len(version1), len(version2), 0, 0
  3. for i &lt; len1 || j &lt; len2 {
  4. n1 := 0
  5. for i &lt; len1 &amp;&amp; &#39;0&#39; &lt;= version1[i] &amp;&amp; version1[i] &lt;= &#39;9&#39; {
  6. n1 = n1 * 10 + int(version1[i] - &#39;0&#39;)
  7. i++
  8. }
  9. n2 := 0
  10. for j &lt; len2 &amp;&amp; &#39;0&#39; &lt;= version2[j] &amp;&amp; version2[j] &lt;= &#39;9&#39; {
  11. n2 = n2 * 10 + int(version2[j] - &#39;0&#39;)
  12. j++
  13. }
  14. if n1 &gt; n2 {
  15. return 1
  16. }
  17. if n1 &lt; n2 {
  18. return -1
  19. }
  20. i, j = i+1, j+1
  21. }
  22. return 0
  23. }

答案10

得分: 0

  1. import (
  2. "fmt"
  3. "strconv"
  4. "strings"
  5. )
  6. func main() {
  7. j := ll("1.05.00.0156", "1.0.221.9289")
  8. fmt.Println(j)
  9. }
  10. func ll(a, b string) int {
  11. var length, r, l int = 0, 0, 0
  12. v1 := strings.Split(a, ".")
  13. v2 := strings.Split(b, ".")
  14. len1, len2 := len(v1), len(v2)
  15. length = len2
  16. if len1 > len2 {
  17. length = len1
  18. }
  19. for i := 0; i < length; i++ {
  20. if i < len1 && i < len2 {
  21. if v1[i] == v2[i] {
  22. continue
  23. }
  24. }
  25. r = 0
  26. if i < len1 {
  27. if number, err := strconv.Atoi(v1[i]); err == nil {
  28. r = number
  29. }
  30. }
  31. l = 0
  32. if i < len2 {
  33. if number, err := strconv.Atoi(v2[i]); err == nil {
  34. l = number
  35. }
  36. }
  37. if r < l {
  38. return -1
  39. } else if r > l {
  40. return 1
  41. }
  42. }
  43. return 0
  44. }

这是一个用Go语言编写的程序,它定义了一个名为ll的函数,该函数接受两个字符串参数ab,并返回一个整数。在main函数中,调用了ll函数,并将结果打印出来。ll函数的功能是比较两个版本号字符串的大小关系,如果a小于b,则返回-1;如果a大于b,则返回1;如果a等于b,则返回0。

英文:
  1. import (
  2. &quot;fmt&quot;
  3. &quot;strconv&quot;
  4. &quot;strings&quot;
  5. )
  6. func main() {
  7. j := ll(&quot;1.05.00.0156&quot; ,&quot;1.0.221.9289&quot;)
  8. fmt.Println(j)
  9. }
  10. func ll(a,b string) int {
  11. var length ,r,l int = 0,0,0
  12. v1 := strings.Split(a,&quot;.&quot;)
  13. v2 := strings.Split(b,&quot;.&quot;)
  14. len1, len2 := len(v1), len(v2)
  15. length = len2
  16. if len1 &gt; len2 {
  17. length = len1
  18. }
  19. for i:= 0;i&lt;length;i++ {
  20. if i &lt; len1 &amp;&amp; i &lt; len2 {
  21. if v1[i] == v2[i] {
  22. continue
  23. }
  24. }
  25. r = 0
  26. if i &lt; len1 {
  27. if number, err := strconv.Atoi(v1[i]); err == nil {
  28. r = number
  29. }
  30. }
  31. l = 0
  32. if i &lt; len2 {
  33. if number, err := strconv.Atoi(v2[i]); err == nil {
  34. l = number
  35. }
  36. }
  37. if r &lt; l {
  38. return -1
  39. }else if r&gt; l {
  40. return 1
  41. }
  42. }
  43. return 0
  44. }

答案11

得分: 0

如果你可以保证版本字符串具有相同的格式(例如SemVer),你可以将其转换为整数并进行比较。这里是一个用于对SemVer切片进行排序的实现:

  1. versions := []string{"1.0.10", "1.0.6", "1.0.9"}
  2. sort.Slice(versions[:], func(i, j int) bool {
  3. as := strings.Split(versions[i], ".")
  4. bs := strings.Split(versions[j], ".")
  5. if len(as) != len(bs) || len(as) != 3 {
  6. return versions[i] < versions[j]
  7. }
  8. ais := make([]int, len(as))
  9. bis := make([]int, len(bs))
  10. for i := range as {
  11. ais[i], _ = strconv.Atoi(as[i])
  12. bis[i], _ = strconv.Atoi(bs[i])
  13. }
  14. //X.Y.Z
  15. // 如果X和Y相同,比较Z
  16. if ais[0] == bis[0] && ais[1] == bis[1] {
  17. return ais[2] < bis[2]
  18. }
  19. // 如果X相同,比较Y
  20. if ais[0] == bis[0] {
  21. return ais[1] < bis[1]
  22. }
  23. // 比较X
  24. return ais[0] < bis[0]
  25. })
  26. fmt.Println(versions)
英文:

If you can guarantee version strings have same format (i.e. SemVer), you can convert to int and compare int. Here is an implementation for sorting slices of SemVer:

  1. versions := []string{&quot;1.0.10&quot;, &quot;1.0.6&quot;, &quot;1.0.9&quot;}
  2. sort.Slice(versions[:], func(i, j int) bool {
  3. as := strings.Split(versions[i], &quot;.&quot;)
  4. bs := strings.Split(versions[j], &quot;.&quot;)
  5. if len(as) != len(bs) || len(as) != 3 {
  6. return versions[i] &lt; versions[j]
  7. }
  8. ais := make([]int, len(as))
  9. bis := make([]int, len(bs))
  10. for i := range as {
  11. ais[i], _ = strconv.Atoi(as[i])
  12. bis[i], _ = strconv.Atoi(bs[i])
  13. }
  14. //X.Y.Z
  15. // If X and Y are the same, compare Z
  16. if ais[0] == bis[0] &amp;&amp; ais[1] == bis[1] {
  17. return ais[2] &lt; bis[2]
  18. }
  19. // If X is same, compare Y
  20. if ais[0] == bis[0] {
  21. return ais[1] &lt; bis[1]
  22. }
  23. // Compare X
  24. return ais[0] &lt; bis[0]
  25. })
  26. fmt.Println(versions)

答案12

得分: 0

解决方案1

这是一个版本比较函数,返回表示两个版本之间关系的符号。

  1. // 如果 v1 > v2 返回 '>'
  2. // 如果 v1 < v2 返回 '<'
  3. // 否则返回 '='
  4. func CompareVersion(v1, v2 string) byte {
  5. v1Slice := strings.Split(v1, ".")
  6. v2Slice := strings.Split(v2, ".")
  7. var maxSize int
  8. { // 使它们具有相同的长度。
  9. if len(v1Slice) < len(v2Slice) {
  10. maxSize = len(v2Slice)
  11. } else {
  12. maxSize = len(v1Slice)
  13. }
  14. }
  15. v1NSlice := make([]int, maxSize)
  16. v2NSlice := make([]int, maxSize)
  17. {
  18. // 将字符串转换为整数。
  19. for i := range v1Slice {
  20. v1NSlice[i], _ = strconv.Atoi(v1Slice[i])
  21. }
  22. for i := range v2Slice {
  23. v2NSlice[i], _ = strconv.Atoi(v2Slice[i])
  24. }
  25. }
  26. var result byte
  27. var v2Elem int
  28. for i, v1Elem := range v1NSlice {
  29. if result != '=' && result != 0 { // 前面的比较已经得到了答案。
  30. return result
  31. }
  32. v2Elem = v2NSlice[i]
  33. if v1Elem > v2Elem {
  34. result = '>'
  35. } else if v1Elem < v2Elem {
  36. result = '<'
  37. } else {
  38. result = '='
  39. }
  40. }
  41. return result
  42. }

go playground

解决方案2

这是另一种更直接的方法。

  1. CmpVer("1.01", "==", "1.001") // true
  1. var (
  2. ErrInvalidOperator = errors.New("invalid operator")
  3. )
  4. func CmpVer(v1, op, v2 string) (bool, error) {
  5. v1Slice := strings.Split(v1, ".")
  6. v2Slice := strings.Split(v2, ".")
  7. var maxSize int
  8. // 让它们具有相同的长度。
  9. if len(v1Slice) < len(v2Slice) {
  10. maxSize = len(v2Slice)
  11. } else {
  12. maxSize = len(v1Slice)
  13. }
  14. v1NSlice := make([]int, maxSize)
  15. v2NSlice := make([]int, maxSize)
  16. var err error
  17. // 将字符串转换为整数。
  18. for i := range v1Slice {
  19. v1NSlice[i], err = strconv.Atoi(v1Slice[i])
  20. if err != nil {
  21. return false, err
  22. }
  23. }
  24. for i := range v2Slice {
  25. v2NSlice[i], err = strconv.Atoi(v2Slice[i])
  26. if err != nil {
  27. return false, err
  28. }
  29. }
  30. var sign rune
  31. var v2Elem int
  32. for i, v1Elem := range v1NSlice {
  33. if sign != '=' && sign != 0 { // 前面的比较已经得到了答案。
  34. break
  35. }
  36. v2Elem = v2NSlice[i]
  37. if v1Elem > v2Elem {
  38. sign = '>'
  39. } else if v1Elem < v2Elem {
  40. sign = '<'
  41. } else {
  42. sign = '='
  43. }
  44. }
  45. switch op {
  46. case ">":
  47. return sign == '>', nil
  48. case ">=":
  49. return sign == '>' || sign == '=', nil
  50. case "==":
  51. fallthrough
  52. case "=":
  53. return sign == '=', nil
  54. case "!=":
  55. return sign != '=', nil
  56. case "<":
  57. return sign == '<', nil
  58. case "<=":
  59. return sign == '<' || sign == '=', nil
  60. default:
  61. return false, fmt.Errorf("%w: %s", ErrInvalidOperator, op)
  62. }
  63. }

playground

英文:

Solution1

This is a version comparison that returns symbols to indicate the relationship between the two versions.

  1. // If v1 &gt; v2 return &#39;&gt;&#39;
  2. // If v1 &lt; v2 return &#39;&lt;&#39;
  3. // Otherwise return &#39;=&#39;
  4. func CompareVersion(v1, v2 string) byte {
  5. v1Slice := strings.Split(v1, &quot;.&quot;)
  6. v2Slice := strings.Split(v2, &quot;.&quot;)
  7. var maxSize int
  8. { // Make them both the same size.
  9. if len(v1Slice) &lt; len(v2Slice) {
  10. maxSize = len(v2Slice)
  11. } else {
  12. maxSize = len(v1Slice)
  13. }
  14. }
  15. v1NSlice := make([]int, maxSize)
  16. v2NSlice := make([]int, maxSize)
  17. {
  18. // Convert string to the int.
  19. for i := range v1Slice {
  20. v1NSlice[i], _ = strconv.Atoi(v1Slice[i])
  21. }
  22. for i := range v2Slice {
  23. v2NSlice[i], _ = strconv.Atoi(v2Slice[i])
  24. }
  25. }
  26. var result byte
  27. var v2Elem int
  28. for i, v1Elem := range v1NSlice {
  29. if result != &#39;=&#39; &amp;&amp; result != 0 { // The previous comparison has got the answer already.
  30. return result
  31. }
  32. v2Elem = v2NSlice[i]
  33. if v1Elem &gt; v2Elem {
  34. result = &#39;&gt;&#39;
  35. } else if v1Elem &lt; v2Elem {
  36. result = &#39;&lt;&#39;
  37. } else {
  38. result = &#39;=&#39;
  39. }
  40. }
  41. return result
  42. }

<kbd>go playground</kbd>

Solution2

This is another more straightforward approach.

  1. CmpVer(&quot;1.01&quot;, &quot;==&quot;, &quot;1.001&quot;) // true
  1. var (
  2. ErrInvalidOperator = errors.New(&quot;invalid operator&quot;)
  3. )
  4. func CmpVer(v1, op, v2 string) (bool, error) {
  5. v1Slice := strings.Split(v1, &quot;.&quot;)
  6. v2Slice := strings.Split(v2, &quot;.&quot;)
  7. var maxSize int
  8. // Let each other have the same length.
  9. if len(v1Slice) &lt; len(v2Slice) {
  10. maxSize = len(v2Slice)
  11. } else {
  12. maxSize = len(v1Slice)
  13. }
  14. v1NSlice := make([]int, maxSize)
  15. v2NSlice := make([]int, maxSize)
  16. var err error
  17. // convert string to int
  18. for i := range v1Slice {
  19. v1NSlice[i], err = strconv.Atoi(v1Slice[i])
  20. if err != nil {
  21. return false, err
  22. }
  23. }
  24. for i := range v2Slice {
  25. v2NSlice[i], err = strconv.Atoi(v2Slice[i])
  26. if err != nil {
  27. return false, err
  28. }
  29. }
  30. var sign rune
  31. var v2Elem int
  32. for i, v1Elem := range v1NSlice {
  33. if sign != &#39;=&#39; &amp;&amp; sign != 0 { // // The previous comparison has got the answer already.
  34. break
  35. }
  36. v2Elem = v2NSlice[i]
  37. if v1Elem &gt; v2Elem {
  38. sign = &#39;&gt;&#39;
  39. } else if v1Elem &lt; v2Elem {
  40. sign = &#39;&lt;&#39;
  41. } else {
  42. sign = &#39;=&#39;
  43. }
  44. }
  45. switch op {
  46. case &quot;&gt;&quot;:
  47. return sign == &#39;&gt;&#39;, nil
  48. case &quot;&gt;=&quot;:
  49. return sign == &#39;&gt;&#39; || sign == &#39;=&#39;, nil
  50. case &quot;==&quot;:
  51. fallthrough
  52. case &quot;=&quot;:
  53. return sign == &#39;=&#39;, nil
  54. case &quot;!=&quot;:
  55. return sign != &#39;=&#39;, nil
  56. case &quot;&lt;&quot;:
  57. return sign == &#39;&lt;&#39;, nil
  58. case &quot;&lt;=&quot;:
  59. return sign == &#39;&lt;&#39; || sign == &#39;=&#39;, nil
  60. default:
  61. return false, fmt.Errorf(&quot;%w: %s&quot;, ErrInvalidOperator, op)
  62. }
  63. }

<kbd>playground</kbd>

答案13

得分: -8

将"1.05.00.0156"转换为"0001"+"0005"+"0000"+"0156",然后转换为int64类型。

将"1.0.221.9289"转换为"0001"+"0000"+"0221"+"9289",然后转换为int64类型。

比较这两个int64值。

Go playground上尝试一下。

英文:

Convert "1.05.00.0156" to "0001"+"0005"+"0000"+"0156", then to int64.

Convert "1.0.221.9289" to "0001"+"0000"+"0221"+"9289", then to int64.

Compare the two int64 values.

Try it on the <kbd>Go playground</kbd>

huangapple
  • 本文由 发表于 2013年8月24日 02:20:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/18409373.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定