Reputation: 9
I want to convert a string representing and integer into a slice containing each integer that made up the initial string.
I've tried using the Atoi()
function in strconv
, it it gives "cannot use toCheck[i] (type byte) as type string in argument to strconv.Atoi". I've also tried int() conversion, but it's giving me what I believe are ASCII values - I know that I can just subtract 48, but that seems a little hacky.
package main
import (
"fmt"
)
func main() {
toCheck := "987654321"
var toSum []int
for i := len(toCheck) - 2; i >= 0; i = i-2 {
toSum = append(toSum, int(toCheck[i]))
}
fmt.Println(toSum)
// expected 2 4 6 8
// actual 50 52 54 56
}
Expected output: 2 4 6 Actual: 50 52 54 56
Upvotes: 1
Views: 2167
Reputation: 166569
For example,
package main
import (
"fmt"
)
func main() {
toCheck := "987654321"
fmt.Println(toCheck)
toSum := make([]int, 0, len(toCheck)/2)
for i := len(toCheck) - 2; i >= 0; i -= 2 {
c := toCheck[i]
if c >= '0' && c <= '9' {
toSum = append(toSum, int(c-'0'))
}
}
fmt.Println(len(toSum), cap(toSum), toSum)
}
Playground: https://play.golang.org/p/wtIgqEKj-Bk
Output:
987654321
4 4 [2 4 6 8]
This is Go. Code should be reasonably efficient. For example,
$ go test sum_test.go -bench=. -benchmem
BenchmarkPeterSO-8 50000000 24.5 ns/op 32 B/op 1 allocs/op
BenchmarkTom-8 20000000 77.6 ns/op 56 B/op 3 allocs/op
BenchmarkUser10753492-8 20000000 79.0 ns/op 56 B/op 3 allocs/op
BenchmarkGrissom-8 20000000 108 ns/op 56 B/op 3 allocs/op
$
sum_test.go
:
package main
import (
"strconv"
"testing"
)
// https://play.golang.org/p/wtIgqEKj-Bk
func BenchmarkPeterSO(b *testing.B) {
toCheck := "987654321"
for N := 0; N < b.N; N++ {
toSum := make([]int, 0, len(toCheck)/2)
for i := len(toCheck) - 2; i >= 0; i -= 2 {
c := toCheck[i]
if c >= '0' && c <= '9' {
toSum = append(toSum, int(c-'0'))
}
}
}
}
// https://play.golang.org/p/KgQrbesy5rT
func BenchmarkTom(b *testing.B) {
toCheck := "987654321"
for N := 0; N < b.N; N++ {
var toSum []int
for i := len(toCheck) - 2; i >= 0; i = i - 2 {
toSum = append(toSum, int(toCheck[i]))
}
}
}
func ByteToInt(c byte) (int, bool) {
if c >= '0' && c <= '9' {
return int(c - '0'), true
} else {
return 0, false
}
}
// https://play.golang.org/p/MRqtgY0ugZY
func BenchmarkUser10753492(b *testing.B) {
toCheck := "987654321"
for N := 0; N < b.N; N++ {
var toSum []int
for i := len(toCheck) - 2; i >= 0; i = i - 2 {
var digit, _ = ByteToInt(toCheck[i])
toSum = append(toSum, digit)
}
}
}
// https://play.golang.org/p/kNbQVn8GJ9R
func BenchmarkGrissom(b *testing.B) {
toCheck := "987654321"
for N := 0; N < b.N; N++ {
var toSum []int
for i := len(toCheck) - 2; i >= 0; i = i - 2 {
v, _ := strconv.Atoi(string(toCheck[i]))
toSum = append(toSum, v)
}
}
}
Upvotes: 1
Reputation: 778
but it's giving me what I believe are ASCII values - I know that I can just subtract 48, but that seems a little hacky.
It's not hacky. You have a byte representing an ascii digit and you want to get its value as an integer from 0-9. That's how you do it. That's also how converting a string to an integer works in general. You convert each individual byte to a number using this method.
The UTF-8 representation for '0' is not going to change anytime soon. Of course, instead of subtracting 48
you can subtract '0'
.
To make it more general purpose, maybe you should also return a boolean indicating whether the byte can be converted or not.
func ByteToInt(c byte) (int, bool) {
if c >= '0' && c <= '9' {
return int(c - '0'), true
} else {
return 0, false
}
}
You can use this in your code sample and it would return your expected result:
package main
import (
"fmt"
)
func ByteToInt(c byte) (int, bool) {
if c >= '0' && c <='9' {
return int(c - '0'), true
} else {
return 0, false
}
}
func main() {
toCheck := "987654321"
var toSum []int
for i := len(toCheck) - 2; i >= 0; i = i-2 {
var digit, _ = ByteToInt(toCheck[i])
toSum = append(toSum, digit)
}
fmt.Println(toSum)
}
https://play.golang.org/p/MRqtgY0ugZY
The output is what you expect: [2 4 6 8]
Upvotes: 2
Reputation: 66
use strconv
package to do the conversion
for i := len(toCheck) - 2; i >= 0; i = i-2 {
v,_ := strconv.Atoi(string(toCheck[i]))
toSum = append(toSum, v)
}
strconv.Atoi is shortcut for strconv.ParseInt(s,10,0).
finish in your playground https://play.golang.org/p/kNbQVn8GJ9R
Upvotes: 0