Go 的 LeftStr、RightStr、SubStr

我相信Go中没有LeftStr(str,n)(最多取n个第一个字符),RightStr(str,n)(最多取n个最后一个字符)和SubStr(str,pos,n)(取pos后的第一个n个字符)函数,所以我尝试制作一个


// take at most n first characters

func Left(str string, num int) string {

    if num <= 0 {

        return ``

    }

    if num > len(str) {

        num = len(str)

    }

    return str[:num]

}


// take at most last n characters

func Right(str string, num int) string {

    if num <= 0 {

        return ``

    }

    max := len(str)

    if num > max {

        num = max

    }

    num = max - num

    return str[num:]

}

但我相信当字符串包含 unicode 字符时,这些函数会给出错误的输出。这些功能最快的解决方案是什么,使用for range循环是唯一的方法吗?


幕布斯6054654
浏览 190回答 1
1回答

慕姐4208626

正如评论中已经提到的,&nbsp;组合字符、修改符文和其他多符文&nbsp;“字符”&nbsp;可能会造成困难。任何对 Go 中的 Unicode 处理感兴趣的人都应该阅读 Go 博客文章“&nbsp;Go 中的&nbsp;字符串、字节、符文和字符”&nbsp;和“Go 中的文本规范化”。特别是,后者讨论了golang.org/x/text/unicode/norm可以帮助处理其中一些问题的包。您可以考虑从字符串中吐出第一个(或最后一个)“n 个字符”的几个级别越来越准确(或越来越多的 Unicode 感知)。只需使用 n 个字节。这可能会在符文的中间分裂,但它是 O(1),非常简单,并且在许多情况下,您知道输入仅由单字节符文组成。例如&nbsp;str[:n]。在 n 个符文后分裂。这可能会在字符的中间分裂。这可以轻松完成,但代价是仅使用string([]rune(str)[:n]).&nbsp;您可以通过使用unicode/utf8包的DecodeRuneInString(and&nbsp;DecodeLastRuneInString) 函数依次获取前 n 个符文中的每个符文的长度,然后返回str[:sum](O(n),无分配)来避免转换和复制。在第 n 个“边界”之后拆分。一种方法是norm.NFC.FirstBoundaryInString(str)重复使用&nbsp;或norm.Iter找到要拆分的字节位置,然后返回str[:pos]。考虑显示的字符串“cafés”,它可以在 Go 代码中表示为:“cafés”、“caf\u00E9s”或“caf\xc3\xa9s”,它们都产生相同的六个字节。或者,它可以表示为“cafe\u0301s”或“cafe\xcc\x81s”,它们都产生相同的七个字节。上面的第一个“方法”可能会将它们拆分为“caf\xc3”+“\xa9s”和cafe\xcc“+”\x81s”。第二个可能将它们拆分为“caf\u00E9”+“s”(“cafe”+“s”)和“cafe”+“\u0301s”(“cafe”+“́s”)。第三个应该将它们分成“caf\u00E9”+“s”和“cafe\u0301”+“s”(都显示为“café”+“s”)。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go