gpt4 book ai didi

ruby - 使用 Unicode 归类算法在 Ruby 中排序

转载 作者:数据小太阳 更新时间:2023-10-29 06:53:55 24 4
gpt4 key购买 nike

Ruby 和 Postgres 的排序方式略有不同,这在我的项目中造成了微妙的问题。有两个问题:重音字符和空格。看起来 Ruby 正在以 ASCII-betical 方式排序,而 Postgres 正在使用正确的 Unicode collation algorithm 进行排序。 .

Heroku Postgres 11.2。数据库排序规则是 en_US.UTF-8

psql (11.3, server 11.2 (Ubuntu 11.2-1.pgdg16.04+1))
...
=> select 'quia et' > 'qui qui';
?column?
----------
f
(1 row)
=> select 'quib' > 'qüia';
?column?
----------
t
(1 row)

Heroku 上的 Ruby 2.4.4。

Loading production environment (Rails 5.2.2.1)
[1] pry(main)> 'quia et' > 'qui qui'
=> true
[2] pry(main)> 'quib' > 'qüia'
=> false
[3] pry(main)> ENV['LANG']
=> "en_US.UTF-8"

我可以修复重音字符的处理,但我无法让 Ruby 正确处理空格。例如,这是他们对同一个列表进行排序的方式。

Postgres: ["hic et illum", "quia et ipsa", "qui qui non"]
Ruby: ["hic et illum", "qui qui non", "quia et ipsa"]

我试过 icunicode gem :

array.sort_by {|s| s.unicode_sort_key}

这会处理重音字符,但不会正确处理空格。

如何让 Ruby 使用 Unicode 归类算法进行排序?

更新 Unicode® Technical Standard #10 中有一个更全面的示例.这些顺序正确。

  [
"di Silva Fred",
"diSilva Fred",
"disílva Fred",
"di Silva John",
"diSilva John",
"disílva John"
]

最佳答案

您的用例是否允许简单地将排序委托(delegate)给 Postgres,而不是尝试在 Ruby 中重新创建它?

部分困难在于没有单一正确的排序方法,但任何可变元素都可能导致最终排序顺序出现相当大的差异,例如见the section on variable weighting .

例如,像 twitter-cldr-rb 这样的 gem有一个相当健壮的 UCA 实现,并由一个全面的测试套件支持 - 但针对不可忽略的测试用例,这与 Postgres 实现不同(Postgres 似乎使用 shift-trimmed 变体)。

test cases 的绝对数量意味着您不能保证一个有效的解决方案将匹配 Postgres 排序顺序在所有情况下。例如。它会正确处理 en/em 破折号,甚至是表情符号吗?您可以 fork 并修改 twitter-cldr-rb gem,但我怀疑这不是一件小事!

如果您需要处理数据库中不存在的值,您可以要求 Postgres 使用 VALUES 列表以轻量级方式对它们进行排序:

sql = "SELECT * FROM (VALUES ('de luge'),('de Luge'),('de-luge'),('de-Luge'),('de-luge'),('de-Luge'),('death'),('deluge'),('deLuge'),('demark')) AS t(term) ORDER BY term ASC"
ActiveRecord::Base.connection.execute(sql).values.flatten

这显然会导致到 Postgres 的往返,但应该非常快。

关于ruby - 使用 Unicode 归类算法在 Ruby 中排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56500689/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com