在RoR中对UTF-8字符串进行排序

Dan*_*uis 15 ruby sorting ruby-on-rails utf-8

我试图找出一种在Ruby on Rails中对UTF-8字符串进行排序的"正确"方法.

在我的应用程序中,我有一个填充了国家/地区的选择框.由于我的应用程序已本地化,因此每个现有语言环境都有一个countries.yml文件,该文件将国家/地区的ID与该国家/地区的本地化名称相关联.我无法在yml文件中手动对字符串进行排序,因为我需要ID在所有语言环境中保持一致.

我所做的是创建一个ascii_name方法,使用unidecodegem将重音和非拉丁字符转换为它们的ascii等价物(例如,"Afeganistão"将成为"Afeganistao"),然后排序:

require 'unidecode'

class Country
  def ascii_name
    Unidecoder.decode(name).gsub("[?]", "").gsub(/`/, "'").strip
  end
end

Country.all.sort_by(:&ascii_name)
Run Code Online (Sandbox Code Playgroud)

但是,这有明显的问题:

  • 它无法正确排序非拉丁语区域设置,因为可能没有直接类似的拉丁字符.
  • 它没有区分字母和该字母的所有重音形式(例如,A和Ä可以互换)

有没有人知道我可以对弦进行排序的更好方法?

tor*_*o2k 10

Ruby peforms string comparisons based on byte values of characters:

%w[à a e].sort
# => ["a", "e", "à"]
Run Code Online (Sandbox Code Playgroud)

To properly collate strings according to locale, the ffi-icu gem could be used:

require "ffi-icu"

ICU::Collation.collate("it_IT", %w[à a e])
# => ["a", "à", "e"]

ICU::Collation.collate("de", %w[a s x ß])
# => ["a", "s", "ß", "x"]
Run Code Online (Sandbox Code Playgroud)

As an alternative:

collator = ICU::Collation::Collator.new("it_IT")
%w[à a e].sort { |a, b| collator.compare(a, b) }
# => %w[a à e]
Run Code Online (Sandbox Code Playgroud)

Update To test how strings should collate according to locale rules the ICU project provides this nice tool.


İ. *_*tlu 8

http://github.com/grosser/sort_alphabetical

这个宝石应该有帮助.它增加了sort_alphabeticalsort_alphabetical_by方法Enumberable.