为了账号安全,请及时绑定邮箱和手机立即绑定

从字符串中删除空字符

从字符串中删除空字符

Go
大话西游666 2023-06-01 17:23:18
我想检查字符串是否为空并及时解析字符串。请找到下面的代码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}如何从字符串中删除这个空字符?或者检查字符串是否包含这个空字符?
查看完整描述

3 回答

?
哆啦的时光机

TA贡献1779条经验 获得超6个赞

您可以\x00像删除任何其他符文一样从字符串中删除符文:


valueStr = strings.Replace(valueStr, "\x00", "", -1)

例子:


s := "a\x00b"

fmt.Printf("%q\n", s)

s = strings.Replace(s, "\x00", "", -1)

fmt.Printf("%q\n", s)

输出(在Go Playground上尝试):


"a\x00b"

"ab"

使用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)

输出(在Go Playground上尝试):


" \t\n\rabc\x00"

"abc"

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


使用strings.Map()

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


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


func remove(r rune) rune {

    switch r {

    case ' ', '\t', '\n', '\r', 0:

        return -1

    }

    return r

}

然后使用它:


s := " \t\n\rabc\x00"

fmt.Printf("%q\n", s)


s = strings.Map(remove, s)

fmt.Printf("%q\n", s)

输出(在Go Playground上尝试):


" \t\n\rabc\x00"

"abc"

基准

我们可能会认为strings.Map()它会更好,因为它只需要处理rune只是数字的 s int32,而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

}

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


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)

            }

        })

    }


}

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


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

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


查看完整回答
反对 回复 2023-06-01
?
泛舟湖上清波郎朗

TA贡献1818条经验 获得超3个赞

在当前的 Python(截至 2021 年 11 月)和 Windows 10 下,这段代码对我有用:

s = str.replace(s, "\x00", "", -1)


查看完整回答
反对 回复 2023-06-01
?
BIG阳

TA贡献1859条经验 获得超6个赞

我不知道这是否是您的情况,但就我而言,我收到了uint16来自 Windows Syscalls 的切片。在这种情况下,数据也由 null 元素终止。为了解决这个问题,你可以使用这个windows包:


package main


import (

   "fmt"

   "golang.org/x/sys/windows"

)


func main() {

   a := []uint16{77, 97, 114, 99, 104, 0}

   s := windows.UTF16ToString(a)

   fmt.Printf("%q\n", s) // "March"

}

查看完整回答
反对 回复 2023-06-01
  • 3 回答
  • 0 关注
  • 150 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信