简体   繁体   English

如何在Golang中将数字转换为格式为1 = A1,2 = A2,…9 = B1,…64 = H8的字符串?

[英]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 . .

String concatenation 字符串串联

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)
}

Byte slice 字节片

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 constant and slicing 字符串常量和切片

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]
}

Dictionary 字典

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]
}

Speed analysis (benchmark) 速度分析(基准)

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进行比较:字典查找比原始串联快一百倍

Using 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM