Разделение юникод-сущностей по графемам
"d̪".chars.to_a
дает мне
["d"," ̪"]
Как мне заставить Ruby разделить его по графемам?
["d̪"]
4 ответа
Решение
Использование Unicode::text_elements
из unicode.gem, который задокументирован по адресу http://www.yoshidam.net/unicode.txt.
irb(main):001:0> require 'unicode'
=> true
irb(main):006:0> s = "abčd̪é"
=> "abčd̪é"
irb(main):007:0> s.chars.to_a
=> ["a", "b", "č", "d", "̪", "é"]
irb(main):009:0> Unicode.nfc(s).chars.to_a
=> ["a", "b", "č", "d", "̪", "é"]
irb(main):010:0> Unicode.nfd(s).chars.to_a
=> ["a", "b", "c", "̌", "d", "̪", "e", "́"]
irb(main):017:0> Unicode.text_elements(s)
=> ["a", "b", "č", "d̪", "é"]
В Ruby 2.0 или выше вы можете использовать str.scan /\X/
> "d̪".scan /\X/
=> ["d̪"]
> "d̪d̪d̪".scan /\X/
=> ["d̪", "d̪", "d̪"]
# Let's get crazy:
> str = 'Z͑ͫ̓ͪ̂ͫ̽͏̴̙̤̞͉͚̯̞̠͍A̴̵̜̰͔ͫ͗͢L̠ͨͧͩ͘G̴̻͈͍͔̹̑͗̎̅͛́Ǫ̵̹̻̝̳͂̌̌͘!͖̬̰̙̗̿̋ͥͥ̂ͣ̐́́͜͞'
> str.length
=> 75
> str.scan(/\X/).length
=> 6
Если вы хотите соответствовать границам графемы по любой причине, вы можете использовать (?=\X)
в вашем регулярном выражении, например:
> "d̪".split /(?=\X)/
=> ["d̪"]
ActiveSupport (который включен в Rails) также есть способ, если вы не можете использовать \X
по какой-то причине:
ActiveSupport::Multibyte::Unicode.unpack_graphemes("d̪").map { |codes| codes.pack("U*") }
Следующий код должен работать в Ruby 2.5:
"d̪".grapheme_clusters # => ["d̪"]
Я не знаю, почему ваш код не дает кодовые точки Unicode, потому что новая версия Ruby всегда дает кодовые точки Unicode при использовании each_char
или же chars
, но вы всегда можете использовать:
"d̪".codepoints.to_a
Это для юникода.