Mam dwa ciągi (w rzeczywistości są numery wersji i mogą być dowolne numery wersji)Jak porównać dwa ciągi numer wersji w golang
a := "1.05.00.0156"
b := "1.0.221.9289"
Chcę porównać, który z nich jest większy. Jak to zrobić w golangu?
Mam dwa ciągi (w rzeczywistości są numery wersji i mogą być dowolne numery wersji)Jak porównać dwa ciągi numer wersji w golang
a := "1.05.00.0156"
b := "1.0.221.9289"
Chcę porównać, który z nich jest większy. Jak to zrobić w golangu?
Konwersja "1.05.00.0156" na "0001" + "0005" + "0000" + "0156", a następnie na int64.
Konwertuj "1.0.221.9289" na "0001" + "0000" + "0221" + "9289", a następnie na int64.
Porównaj dwie wartości int64.
Spróbuj na Go playground
To zależy co masz na myśli przez większe.
Naiwny podejście byłoby:
package main
import "fmt"
import "strings"
func main() {
a := strings.Split("1.05.00.0156", ".")
b := strings.Split("1.0.221.9289", ".")
for i, s := range a {
var ai, bi int
fmt.Sscanf(s, "%d", &ai)
fmt.Sscanf(b[i], "%d", &bi)
if ai > bi {
fmt.Printf("%v is bigger than %v\n", a, b)
break
}
if bi > ai {
fmt.Printf("%v is bigger than %v\n", b, a)
break
}
}
}
Dla' a: = stringów.Split ("1", "."); b: = stringów.Split ("1.0.1", ".") ' , dwie ostatnie wersje Go, wynikiem jest '[brak wyjścia]'. – peterSO
tak, jak powiedziałem bardzo naiwną wersję –
Oto ogólne rozwiązanie.
package main
import "fmt"
func VersionOrdinal(version string) string {
// ISO/IEC 14651:2011
const maxByte = 1<<8 - 1
vo := make([]byte, 0, len(version)+8)
j := -1
for i := 0; i < len(version); i++ {
b := version[i]
if '0' > b || b > '9' {
vo = append(vo, b)
j = -1
continue
}
if j == -1 {
vo = append(vo, 0x00)
j = len(vo) - 1
}
if vo[j] == 1 && vo[j+1] == '0' {
vo[j+1] = b
continue
}
if vo[j]+1 > maxByte {
panic("VersionOrdinal: invalid version")
}
vo = append(vo, b)
vo[j]++
}
return string(vo)
}
func main() {
versions := []struct{ a, b string }{
{"1.05.00.0156", "1.0.221.9289"},
// Go versions
{"1", "1.0.1"},
{"1.0.1", "1.0.2"},
{"1.0.2", "1.0.3"},
{"1.0.3", "1.1"},
{"1.1", "1.1.1"},
{"1.1.1", "1.1.2"},
{"1.1.2", "1.2"},
}
for _, version := range versions {
a, b := VersionOrdinal(version.a), VersionOrdinal(version.b)
switch {
case a > b:
fmt.Println(version.a, ">", version.b)
case a < b:
fmt.Println(version.a, "<", version.b)
case a == b:
fmt.Println(version.a, "=", version.b)
}
}
}
wyjściowa:
1.05.00.0156 > 1.0.221.9289
1 < 1.0.1
1.0.1 < 1.0.2
1.0.2 < 1.0.3
1.0.3 < 1.1
1.1 < 1.1.1
1.1.1 < 1.1.2
1.1.2 < 1.2
Jakiś czas temu stworzyłem Porównanie wersji biblioteki: https://github.com/mcuadros/go-version
version.CompareSimple("1.05.00.0156", "1.0.221.9289")
//Returns: 1
spodoba!
Awesome, dzięki! Proszę nie zdejmować go z GitHub w każdej chwili w następnej dekadzie: D –
podstawie Jeremy Walla odpowiedź:
func compareVer(a, b string) (ret int) {
as := strings.Split(a, ".")
bs := strings.Split(b, ".")
loopMax := len(bs)
if len(as) > len(bs) {
loopMax = len(as)
}
for i := 0; i < loopMax; i++ {
var x, y string
if len(as) > i {
x = as[i]
}
if len(bs) > i {
y = bs[i]
}
xi,_ := strconv.Atoi(x)
yi,_ := strconv.Atoi(y)
if xi > yi {
ret = -1
} else if xi < yi {
ret = 1
}
if ret != 0 {
break
}
}
return
}
dążenie do przejrzystości i prostoty:
func intVer(v string) (int64, error) {
sections := strings.Split(v, ".")
intVerSection := func(v string, n int) string {
if n < len(sections) {
return fmt.Sprintf("%04s", sections[n])
} else {
return "0000"
}
}
s := ""
for i := 0; i < 4; i++ {
s += intVerSection(v, i)
}
return strconv.ParseInt(s, 10, 64)
}
func main() {
a := "3.045.98.0832"
b := "087.2345"
va, _ := intVer(a)
vb, _ := intVer(b)
fmt.Println(va<vb)
}
Porównywanie wersji zakłada parsowania więc wierzę te 2 kroki powinny być oddzielone, aby jest solidny.
import (
"fmt"
"strconv"
"strings"
)
func main() {
j := ll("1.05.00.0156" ,"1.0.221.9289")
fmt.Println(j)
}
func ll(a,b string) int {
var length ,r,l int = 0,0,0
v1 := strings.Split(a,".")
v2 := strings.Split(b,".")
len1, len2 := len(v1), len(v2)
length = len2
if len1 > len2 {
length = len1
}
for i:= 0;i<length;i++ {
if i < len1 && i < len2 {
if v1[i] == v2[i] {
continue
}
}
r = 0
if i < len1 {
if number, err := strconv.Atoi(v1[i]); err == nil {
r = number
}
}
l = 0
if i < len2 {
if number, err := strconv.Atoi(v2[i]); err == nil {
l = number
}
}
if r < l {
return -1
}else if r> l {
return 1
}
}
return 0
}
Jest miły rozwiązanie z Hashicorp - https://github.com/hashicorp/go-version
import github.com/hashicorp/go-version
v1, err := version.NewVersion("1.2")
v2, err := version.NewVersion("1.5+metadata")
// Comparison example. There is also GreaterThan, Equal, and just
// a simple Compare that returns an int allowing easy >=, <=, etc.
if v1.LessThan(v2) {
fmt.Printf("%s is less than %s", v1, v2)
}
Ów pracy jako mistrz. Super fajne. Dzięki @Everton. Dlaczego tak, dlaczego dokonać konwersji na int64? Czy nie można tego porównać wcześniej? – JVK
Tak, można go porównać jako ciąg, ale nie wiem, jak porównać ciągi leksykalnie w Go. Potrzebujesz badań. :-) – Everton
To będzie działać tak długo, jak zawsze będzie taka sama liczba cyfr w każdym ciągu wersji. Ale jeśli "2.o" ma być większe niż "1.9.8.6247", to nie zadziała. Zobacz poniżej moją odpowiedź na podejście, które zadziała w takim przypadku. –