【问题标题】:Sort values using a specific collation in Ruby/Rails使用 Ruby/Rails 中的特定排序规则对值进行排序
【发布时间】:2011-07-24 20:31:48
【问题描述】:

是否可以在 Ruby 中使用特定的排序规则对值数组进行排序?我需要根据 da_DK 排序规则进行排序。

给定数组%w(Aarhus Aalborg Assens),我想返回['Assens', 'Aalborg', 'Aarhus'],这是丹麦语的正确顺序。

标准排序方法

%w(Aarhus Aalborg Assens).sort

返回一些看起来像 ascii 顺序的东西(至少不是丹麦顺序):

["Aalborg", "Aarhus", "Assens"]

环境是 Snow Leopard 和运行 ruby​​ 1.9.2 和 Rails 3.0.5 的 linux。

【问题讨论】:

  • 你能解释一下丹麦的订购吗?字母顺序是否与英语不同?
  • 铁皮人在他的回答中解释了这一点。许多语言对特殊字符和字符组合都有特殊的规则。这些规则由排序规则定义,例如da_DK 表示丹麦语 og sv_SE 表示瑞典语。

标签: ruby-on-rails ruby ruby-on-rails-3 internationalization collation


【解决方案1】:

根据Wikipedia

在丹麦语和挪威语字母表中,也出现了与瑞典语相同的额外元音(见下文),但顺序和字形不同(...、X、Y、Z、Æ、Ø、Å) .此外,“Aa”作为“Å”的等价物进行整理。丹麦字母传统上将“W”视为“V”的变体,但今天“W”被视为一个单独的字母。”

这会导致排序失败。

这样做可以解决问题:

names = %w(Aarhus Aalborg Assens)
names.sort_by { |w| w.gsub('Aa', 'Å') } # => ["Assens", "Aalborg", "Aarhus"]

对于具有复合字符组合以转换为单个字符的其他字母来说,类似的东西。

之所以如此,是因为sort_by 做了一个Schwartzian Transformation,所以它实际上是按照从块返回的返回值进行排序的,在这种情况下,是用“Å”替换了“Aa”的名称。替换是临时的,并在数组排序时被丢弃。

sort_by 非常强大,但确实有一些开销。对于简单的排序,您应该使用sort,因为它更快。对于您在对象的顶层比较两个简单值的排序,那么无论您应该使用sort 还是sort_by,都将成为一种洗牌。如果您必须进行更复杂的计算或挖掘对象,那么sort_by 可以证明更快。没有真正的硬性方法可以知道哪个更好,因此如果您必须对大型数组或处理对象进行排序,我强烈建议您使用基准测试,因为差异可能很大,有时sort 可以是更好的选择。

编辑:

Ruby 本身不会做你想做的事,因为它不知道每个字符的排序顺序。有一个 discussion 关于合并 IBM's ICU 解释了为什么会这样。如果您想要 ICU 的能力,您可以查看ICU4R。我没有玩过它,但这听起来像是你在 Ruby 中唯一真正的解决方案。

您也许可以使用 Postgres 之类的数据库做一些事情。它们支持各种排序选项,但通常会强制您在创建数据库时声明排序规则......或者可能是在创建表时......自从我创建新表以来已经有一段时间了。无论如何,这将是一个选择,虽然它会很痛苦。

【讨论】:

  • 我正在寻找一个按排序规则排序的通用解决方案。所有替换和规则都由排序规则定义,我不想在比较完成之前手动更改文本。它容易出错,我想性能不是很好。另外,当我突然需要支持另一种语言时,我将不得不重新开始:/
  • +1 表示答案的“编辑”部分。 icu4r 看起来非常无人维护。也许检查这个叉子:github.com/noahdiewald/icu4r
【解决方案2】:

我在 Github 上找到了 ffi-locale,据我所知,这解决了我的问题。

它允许以下代码:

FFILocale::setlocale FFILocale::LC_COLLATE, 'da_DK.UTF-8'
%w(Aarhus Aalborg Assens).sort { |a,b| FFILocale::strcoll(a, b) }

返回正确的结果:

=> ["Assens", "Aalborg", "Aarhus"]

我还没有调查性能,但它调用了本机代码,所以它应该比 Ruby 字符替换代码更快......

更新
它并不完美:(它在 Snow Leopard 上无法正常工作 - 似乎 strcoll 功能在 OS X 上已损坏并且已经有一段时间了。这对我来说很烦人,但主要的部署平台是 linux - 它工作的地方- 所以这是我目前首选的解决方案。

【讨论】:

    猜你喜欢
    • 2012-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-04
    • 1970-01-01
    • 2011-05-16
    • 1970-01-01
    相关资源
    最近更新 更多