我想使用localeCompare测试通过Postgres排序的字符串。
使用的排序规则是en_US.utf8
当我使用localeCompare测试降序和升序排序时,这给了我错误的结果。我可以将哪种语言环境传递给localeCompare来正确处理?
例如:Descending: "negative outcome".localeCompare("a sollicitudin orci") = 1
Ascending: "amet lorem semper auctor.".localeCompare("a sollicitudin orci") = 1
最佳答案
不幸的是,没有参数可以传递给localeCompare以使其与Postgres的en_US.UTF-8排序相匹配。
Postgres正在遵循Unicode排序算法的实现,该文档在此处记录:http://www.unicode.org/reports/tr10/
相反,localeCompare使用Intl.Collator对象中的“ CompareStrings”操作。根据规范,“两个字符串以实现定义的方式进行比较。” (https://www.ecma-international.org/ecma-402/1.0/#CompareStrings)。该规范建议实现使用Unicode归类算法,但这只是一个建议,尽管我不确定到底是什么浏览器在做什么,但我已经在Mac上的Chrome上进行了足够的经验测试,以确保无论使用哪种浏览器这样做,与Postgres的实现有很大不同。
我目前不知道任何将Unicode排序算法移植到javascript的库。
所以。如果您绝对需要与Postgres排序完全匹配的浏览器端算法,而这是生死攸关的话,那么我认为您的唯一选择是实际查看规范(http://www.unicode.org/reports/tr10/),并可能查看Postgres的源代码和端口。它的JavaScript。
规范非常密集和复杂,因此实用的方法可能是开发一种足够好的算法,该算法在大多数时间都与Postgres匹配,并让您的应用程序优雅地处理极端情况。我找到的最有用的资源是答案https://stackoverflow.com/a/3266430/534086,它使用Latin1归类表提供了该算法的简单实现,该表很可能适合使用UTF8。
就我的目的而言,我还没有走那条路。我写了一个更粗略的算法:a)首先从两个字符串中去除特殊字符,例如空格和&符,然后使用localeCompare和'en-US'比较它们,以及b)打破平局,使用localeCompare比较原始字符串。这是非常粗糙的(我有一些测试用例,我知道它无法使用),但实际上,在我至少90%的实际使用中,它似乎都能产生与Postgres相同的结果。