从字符串中删除空字符

Bha*_*ana 6 string replace go removing-whitespace

我想检查字符串是否为空并及时解析字符串.

请找到以下代码

valueStr = strings.Replace(string(valueStr), " ", "", -1)
valueStr = strings.Replace(string(valueStr), "\t", "", -1)
valueStr = strings.Replace(string(valueStr), "\n", "", -1)
valueStr = strings.Replace(string(valueStr), "\r", "", -1)
var re = regexp.MustCompile(`\s`)
valueStr = re.ReplaceAllString(valueStr, "")

if valueStr != "" {
    fmt.Printf("-------- valueStr %c: \n", valueStr)         // o/p =>  -------- valueStr %!c(string= ):
    fmt.Printf("-------- valueStr %#v: \n", valueStr)        // o/p => -------- valueStr "\x00":
    fmt.Printf("-------- valueStr %x: \n", valueStr)         // o/p =>  -------- valueStr 00:
    fmt.Println("-------- valueStr length: ", len(valueStr)) // o/p => -------- valueStr length:  1

    // considering valueStr is not empty, parse string to time

    time, err := time.Parse(TIME_FORMAT, strings.TrimSpace(valueStr))
    if err != nil {
        fmt.Println("-------- Error converting time: ", err) // o/p => -------- Error converting time:  parsing time " " as "15:04:05": cannot parse " " as "15"
        return
    }
} else {
    // another code
}
Run Code Online (Sandbox Code Playgroud)

如何从字符串中删除此空字符?或者检查字符串是否包含此空字符?

icz*_*cza 9

您可以\x00使用与删除任何其他符文相同的方式从字符串中删除符文:

valueStr = strings.Replace(valueStr, "\x00", "", -1)
Run Code Online (Sandbox Code Playgroud)

例:

s := "a\x00b"
fmt.Printf("%q\n", s)
s = strings.Replace(s, "\x00", "", -1)
fmt.Printf("%q\n", s)
Run Code Online (Sandbox Code Playgroud)

输出(在Go Playground上试试):

"a\x00b"
"ab"
Run Code Online (Sandbox Code Playgroud)

运用 strings.Replacer

另请注意,您可以使用单个操作替换多个替换 strings.Replacer,并且它也会更高效,因为它只迭代输入一次(并且只有一个string为结果分配,无论您想要多少个子串)取代).

例如:

s := " \t\n\rabc\x00"
fmt.Printf("%q\n", s)

r := strings.NewReplacer(" ", "", "\t", "", "\n", "", "\r", "", "\x00", "")
s = r.Replace(s)
fmt.Printf("%q\n", s)
Run Code Online (Sandbox Code Playgroud)

输出(在Go Playground上试试):

" \t\n\rabc\x00"
"abc"
Run Code Online (Sandbox Code Playgroud)

还要注意,创建string.Replacer一次就足够了,你可以将它存储在一个(全局)变量中并重用它,从多个goroutine中同时使用它甚至是安全的.

运用 strings.Map()

另请注意,如果您只想替换(删除)单个runes而不是多符号(或多字节)子串,您还可以使用strings.Map()哪个子串可能更有效strings.Replacer.

首先定义一个函数,告诉rune要替换哪个s(如果返回负值,则删除):

func remove(r rune) rune {
    switch r {
    case ' ', '\t', '\n', '\r', 0:
        return -1
    }
    return r
}
Run Code Online (Sandbox Code Playgroud)

然后使用它:

s := " \t\n\rabc\x00"
fmt.Printf("%q\n", s)

s = strings.Map(remove, s)
fmt.Printf("%q\n", s)
Run Code Online (Sandbox Code Playgroud)

输出(在Go Playground上试试):

" \t\n\rabc\x00"
"abc"
Run Code Online (Sandbox Code Playgroud)

基准

我们可能会认为它strings.Map()会更优越,因为它只需要处理rune只是int32数字的s ,而strings.Replacer必须处理string标题(长度+数据指针)加上一系列字节的值.

但是我们应该知道string值在内存中存储为UTF-8字节序列,这意味着strings.Map()必须rune从UTF-8字节序列解码s(并在最后将符文编码回UTF-8),而strings.Replacer不是:它可以简单地查找字节序列匹配而不解码runes.并且strings.Replacer经过高度优化以利用这些"技巧".

那么让我们创建一个比较它们的基准:

我们将这些用于基准测试:

var r = strings.NewReplacer(" ", "", "\t", "", "\n", "", "\r", "", "\x00", "")

func remove(r rune) rune {
    switch r {
    case ' ', '\t', '\n', '\r', 0:
        return -1
    }
    return r
}
Run Code Online (Sandbox Code Playgroud)

我们在不同的输入字符串上运行基准测试:

func BenchmarkReplaces(b *testing.B) {
    cases := []struct {
        title string
        input string
    }{
        {
            title: "None",
            input: "abc",
        },
        {
            title: "Normal",
            input: " \t\n\rabc\x00",
        },
        {
            title: "Long",
            input: "adsfWR \t\rab\nc\x00 \t\n\rabc\x00asdfWER\n\r",
        },
    }

    for _, c := range cases {
        b.Run("Replacer-"+c.title, func(b *testing.B) {
            for i := 0; i < b.N; i++ {
                r.Replace(c.input)
            }
        })
        b.Run("Map-"+c.title, func(b *testing.B) {
            for i := 0; i < b.N; i++ {
                strings.Map(remove, c.input)
            }
        })
    }

}
Run Code Online (Sandbox Code Playgroud)

现在让我们看看基准测试结果:

BenchmarkReplaces/Replacer-None-4    100000000   12.3 ns/op    0 B/op  0 allocs/op
BenchmarkReplaces/Map-None-4         100000000   16.1 ns/op    0 B/op  0 allocs/op
BenchmarkReplaces/Replacer-Normal-4  20000000    92.7 ns/op    6 B/op  2 allocs/op
BenchmarkReplaces/Map-Normal-4       20000000    92.4 ns/op   16 B/op  2 allocs/op
BenchmarkReplaces/Replacer-Long-4     5000000   234 ns/op     64 B/op  2 allocs/op
BenchmarkReplaces/Map-Long-4          5000000   235 ns/op     80 B/op  2 allocs/op
Run Code Online (Sandbox Code Playgroud)

尽管有所期待,但string.Replacer表现还不错,strings.Map()因为它不需要解码和编码符文.