V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
usamoi
V2EX  ›  问与答

使用可变长度编码作为内部形式的字符串,如何实现访问某个具体位置的字符?

  •  1
     
  •   usamoi · 2021-01-09 00:22:04 +08:00 · 767 次点击
    这是一个创建于 1452 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我在编写一个不可变 String 的轮子,面向处理中文文本较多的环境,希望能减少使用者的心智负担。目前计划使用 UTF-16 作为字符串的内部表示,由于 UTF-16 是变长编码,取得某个位置上的 Unicode Character 这个函数不易实现。单个 Unicode Character 可能占用 1 个 Unicode Code Unit,也可能占用 2 个 Unicode Code Unit,第 k 个 Unicode Code Unit 不一定对应第 k 个 Unicode Character 。

    下面是我目前想到的几个解决方案:

    • 避免问题。改换 UTF-32 作为内部表示。日常场景中只方便了 emoji 的处理,但是这也并不完全,因为一部分 emoji 又需要甚至 3 个 Unicode Character 才能表示出来,依然需要手工处理,所以尤其滑稽。

    • 转移矛盾。和 String 配套的 Character,表示能力从 Unicode Character 缩小到 Unicode Code Unit 。要求使用者自行处理需要 2 个 Unicode Code Unit 表示的字符。这也是.NET 的方案。

    • 加速顺序访问的一个策略。记录上一次访问的 Code Unit 位置和 Character 位置,用来加速下一次访问。为了对并行友好,还需要写一个 StringAccessor 来存储这两项,并且由它间接访问 String,以免不同线程访问同一字符串时这一加速失效。

    • 加速随机访问的一个策略。将字符串均匀分为$O(\sqrt{n})$段,预处理每一段的 Character 数和每一段的 Code Unit 数目,随机访问的时间复杂度为$O(\sqrt{n})$,单个字符串需要$O(\sqrt{n})$的附加空间,代价依然很昂贵。

    这个怎么整啊╮(╯▽╰)╭

    4 条回复    2021-01-09 01:27:40 +08:00
    msg7086
        1
    msg7086  
       2021-01-09 00:33:59 +08:00   ❤️ 1
    要自己扛的话可以考虑加索引。
    比如每 128 字符记一个下标,这样每次寻址最多只需要检查 127 个字符,和你的#4 类似。
    sqrt(n)是一个很不昂贵的操作了,额外的空间和时间基本可以忽略不计。
    要便捷性总要有牺牲的。
    gyf304
        2
    gyf304  
       2021-01-09 00:34:26 +08:00   ❤️ 1
    建议不要自己弄。用 ICU
    http://site.icu-project.org/home
    agagega
        3
    agagega  
       2021-01-09 01:18:05 +08:00 via iPad
    可以加速,但概念上 String 和 Bytes 就不是一个东西,String 可以当作一个无法随机访问的东西
    lxilu
        4
    lxilu  
       2021-01-09 01:27:40 +08:00 via iPhone   ❤️ 1
    有 UTF-X Code Unit
    没有 Unicode Code Unit
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1017 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 20:15 · PVG 04:15 · LAX 12:15 · JFK 15:15
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.