[英]How to convert a number to string, of the form 1=A1, 2=A2, … 9=B1, … 64=H8 in Golang?
This code is giving A1..A9, B0..B9, C0..C9, ...
. 这段代码给出了
A1..A9, B0..B9, C0..C9, ...
But I only want A1..A8, B1..B8, C1..C8, D1..D8, E1..E8, F1..F8, G1..G8, H1..H8
(1-64). 但是我只想要
A1..A8, B1..B8, C1..C8, D1..D8, E1..E8, F1..F8, G1..G8, H1..H8
(1-64)。
package main
import (
"fmt"
)
func ToString(n int8) string {
return string((n/10)+65) + string(((n%10)+49)-1)
}
func main() {
var i int8
for i = 1; i < 11; i++ {
fmt.Println(ToString(i))
}
}
Firstly, you're dividing by the wrong number. 首先,您要除以错误的数字。 If you want the numbers only up to 8, you need to divide by 8.
如果您希望数字最多为8,则需要除以8。
Secondly, you don't need to subtract one in the second string, but you do need to decrease the n
. 其次,您不需要在第二个字符串中减去一个,但是您确实需要减少
n
。
func ToString(n int8) string {
n--
return string((n/8)+65) + string((n%8)+49)
}
func main() {
var i int8
for i = 1; i <= 64; i++ {
fmt.Println(ToString(i))
}
}
https://play.golang.org/p/BdAce3C5JL https://play.golang.org/p/BdAce3C5JL
Let's see different approaches and performance improvements. 让我们看看不同的方法和性能改进。
All the solutions and the benchmarking code can be found on the Go Playground . 所有解决方案和基准测试代码都可以在Go Playground上找到。 The code on the Playground is a test file, not an executable.
Playground上的代码是测试文件,而不是可执行文件。 You have to save it into a file named
XX_test.go
and run it with go test -bench .
您必须将其保存到名为
XX_test.go
的文件中,然后使用go test -bench .
运行它go test -bench .
. 。
Ainar-G's answer is cool (+1): Ainar-G的答案很酷(+1):
func ToStringConcat(n byte) string {
n--
return string((n/8)+65) + string((n%8)+49)
}
But note that the previous solution concatenates 2 string
values which is "costly" especially if we want to call this ToString()
many times. 但是请注意,先前的解决方案将2个
string
值连接在一起,这很“昂贵”,尤其是当我们要多次调用此ToString()
。
One might think that we could spare the string
concatenation if we would try to convert a single integer number containing the 2 codes (the first shifted left by 8 bits), but that wouldn't work as converting integer numbers to string
results in a string
value with a single rune
(a string
containing the UTF-8 representation of the integer). 有人可能会认为,如果我们尝试转换包含2个代码的单个整数(第一个左移8位),则可以省去
string
连接,但是,由于将整数转换为string
导致string
无效带有单个rune
值(包含整数的UTF-8表示形式的string
)。
But we may use a []byte
with 2 values (the letter code and the digit code), and then we only need to convert this single slice value to string
: 但是我们可以使用带有2个值(字母代码和数字代码)的
[]byte
,然后只需要将此单个slice值转换为string
:
func ToStringSlice(n byte) string {
n--
return string([]byte{(n / 8) + 65, (n % 8) + 49})
}
string
values are slicable in Go which results in a new string
(new string
header). string
值在Go中可分割 ,从而产生一个新string
(新string
标题)。 So we may use a string
constant of all the values, and do a simple slicing to get the part we need: 因此,我们可以使用所有值的
string
常量,并进行简单的切片以获得所需的部分:
const values = " A1A2A3A4A5A6A7A8B1B2B3B4B5B6B7B8C1C2C3C4C5C6C7C8D1D2D3D4D5D6D7D8E1E2E3E4E5E6E7E8F1F2F3F4F5F6F7F8G1G2G3G4G5G6G7G8H1H2H3H4H5H6H7H8"
func ToStringConst(n byte) string {
n *= 2
return values[n : n+2]
}
Even though slicing a string
results in a substring which shares the underlying array, it sill needs to create a new string
header. 即使切片
string
导致子字符串共享基础数组,但仍然需要创建新的string
标题。
Since we don't have a lot of possible values, best (fastest) solution is to prepare all the possible values, and just do a simple lookup. 由于我们没有很多可能的值,因此最好(最快)的解决方案是准备所有可能的值,然后进行简单的查找。 Since input is a number, we don't even need a
map
, we can use a simple []string
slice: 由于输入是一个数字,我们甚至不需要
map
,我们可以使用一个简单的[]string
slice:
var dict = []string{"",
"A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8",
"B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8",
"C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8",
"D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8",
"E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8",
"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8",
"G1", "G2", "G3", "G4", "G5", "G6", "G7", "G8",
"H1", "H2", "H3", "H4", "H5", "H6", "H7", "H8",
}
func ToStringDict(n byte) string {
return dict[n]
}
Let's benchmark speed of the above solutions: 让我们对上述解决方案的速度进行基准测试:
func BenchmarkConcat(b *testing.B) {
for i := 0; i < b.N; i++ { ToStringConcat(1) }
}
func BenchmarkSlice(b *testing.B) {
for i := 0; i < b.N; i++ { ToStringSlice(1) }
}
func BenchmarkConst(b *testing.B) {
for i := 0; i < b.N; i++ { ToStringConst(1) }
}
func BenchmarkDict(b *testing.B) {
for i := 0; i < b.N; i++ { ToStringDict(1) }
}
Result: 结果:
BenchmarkConcat-4 20000000 106 ns/op
BenchmarkSlice-4 100000000 17.0 ns/op
BenchmarkConst-4 2000000000 1.34 ns/op
BenchmarkDict-4 2000000000 1.04 ns/op
Just by jumping from concatenation to slice conversion, it immediately becomes 6 times faster . 只需从串联转换为切片转换,转换速度立即提高6倍 。
Utilizing string slicing, we again make it 12 times faster . 利用字符串切片,我们再次使其快了12倍 。
And pre-building all possible values and just doing a simple lookup, we further gain 22% . 预先构建所有可能的值并进行简单的查找,我们进一步获得了22%的收益 。
Comparing the final to the initial: the dictionary lookup is a hundred times faster than the original concatenation. 将final与initial进行比较:字典查找比原始串联快一百倍 。
fmt
fmt
For completeness, here's a solution using the fmt
package: 为了完整
fmt
,以下是使用fmt
软件包的解决方案:
func ToStringFmt(n byte) string {
n--
return fmt.Sprintf("%c%c", (n/8)+65, (n%8)+49)
}
But this one is slower by almost 2.5 times even than our slowest String concatenation solution, as this has to wrap arguments into interface{}
values, create and put them into a slice (for the vararg), has to parse and analyze a format string
, use reflection to process arguments, build the string
representation in a buffer which finally is used to produce the returned string
value. 但这比我们最慢的String串联解决方案要慢将近2.5倍,因为它必须将参数包装到
interface{}
值中,创建并将它们放入切片(对于vararg),必须解析和分析格式string
,使用反射来处理参数,在缓冲区中构建string
表示形式,该缓冲区最终用于产生返回的string
值。 A lot of things happen which are for the "general" case and are not required for our "special" case. 很多事情发生在“一般”情况下,而在我们的“特殊”情况下并不需要。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.