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

Go 的 LeftStr、RightStr、SubStr

Go 的 LeftStr、RightStr、SubStr

Go
幕布斯6054654 2021-09-27 16:09:44
我相信Go中没有LeftStr(str,n)(最多取n个第一个字符),RightStr(str,n)(最多取n个最后一个字符)和SubStr(str,pos,n)(取pos后的第一个n个字符)函数,所以我尝试制作一个// take at most n first charactersfunc 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 charactersfunc 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循环是唯一的方法吗?
查看完整描述

1 回答

?
慕姐4208626

TA贡献1852条经验 获得超7个赞

正如评论中已经提到的, 组合字符、修改符文和其他多符文 “字符” 可能会造成困难。

任何对 Go 中的 Unicode 处理感兴趣的人都应该阅读 Go 博客文章“ Go 中的 字符串、字节、符文和字符” 和“Go 中的文本规范化”。特别是,后者讨论了golang.org/x/text/unicode/norm可以帮助处理其中一些问题的包。

您可以考虑从字符串中吐出第一个(或最后一个)“n 个字符”的几个级别越来越准确(或越来越多的 Unicode 感知)。

  1. 只需使用 n 个字节。这可能会在符文的中间分裂,但它是 O(1),非常简单,并且在许多情况下,您知道输入仅由单字节符文组成。例如 str[:n]

  2. 在 n 个符文后分裂。这可能会在字符的中间分裂。这可以轻松完成,但代价是仅使用string([]rune(str)[:n]). 您可以通过使用unicode/utf8包的DecodeRuneInString(and DecodeLastRuneInString) 函数依次获取前 n 个符文中的每个符文的长度,然后返回str[:sum](O(n),无分配)来避免转换和复制。

  3. 在第 n 个“边界”之后拆分。一种方法是norm.NFC.FirstBoundaryInString(str)重复使用 或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”)。


查看完整回答
反对 回复 2021-09-27
  • 1 回答
  • 0 关注
  • 189 浏览
慕课专栏
更多

添加回答

举报

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