如何在 JavaScript 中对字符串进行排序

IT技术 javascript string
2021-01-27 01:35:45

我有一个对象列表,我希望根据attr字符串类型的字段进行排序我尝试使用-

list.sort(function (a, b) {
    return a.attr - b.attr
})

但发现它-似乎不适用于 JavaScript 中的字符串。如何根据类型为字符串的属性对对象列表进行排序?

6个回答

String.prototype.localeCompare根据您的示例使用一个:

list.sort(function (a, b) {
    return ('' + a.attr).localeCompare(b.attr);
})

我们强制 a.attr 为字符串以避免异常。自 Internet Explorer 6和 Firefox 1localeCompare起就已受支持。您可能还会看到使用了以下不考虑区域设置的代码:

if (item1.attr < item2.attr)
  return -1;
if ( item1.attr > item2.attr)
  return 1;
return 0;
请注意,localeCompare()仅在现代浏览器中受支持:撰写本文时的 IE11+,请参阅developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
2021-03-13 01:35:45
在有人像我一样犯同样的草率错误之前,它是 local e Compare,而不是 localCompare。
2021-03-16 01:35:45
@Shog9 我不好,它似乎从 IE6 开始就支持了!msdn.microsoft.com/en-us/library/ie/s4esdbwz(v=vs.94).aspx上查看(向下滚动/搜索到 localeCompare() 方法)不过需要注意的一点是,在我们不使用语言环境和选项参数的旧实现中(IE11 之前使用的那个),所使用的语言环境和排序顺序完全依赖实现,换句话说:Firefox、Safari、Chrome 和 IE 做不要以相同的顺序对字符串进行排序。请参阅code.google.com/p/v8/issues/detail?id=459
2021-03-22 01:35:45
第一个解决方案将考虑“A”在“z”之后但在“Z”之前,因为它正在对字符 ASCII 值进行比较。localeCompare()不会遇到这个问题,但不会理解数字,所以你会得到 [ "1", "10", "2" ] 就像大多数语言中的排序比较一样。如果您想对 UI 前端进行排序,请查看字母/自然排序算法stackoverflow.com/questions/4340227 /...stackoverflow.com/questions/4321829/...
2021-03-27 01:35:45
不,我的意思是表格的第一行,@Adrien - IE 支持localeCompare()返回多个版本,但不支持版本 11 之前指定语言环境。还要注意 Dead.Rabit 链接到的问题。
2021-04-08 01:35:45

更新的答案(2014 年 10 月)

我真的对这个字符串自然排序顺序很恼火,所以我花了很多时间来调查这个问题。我希望这有帮助。

长话短说

localeCompare()角色支持很糟糕,只需使用它。正如所指出的Shog9,你的问题的答案是:

return item1.attr.localeCompare(item2.attr);

在所有自定义 javascript“自然字符串排序顺序”实现中发现的错误

有很多自定义实现,试图更准确地进行字符串比较,称为“自然字符串排序顺序”

当“玩”这些实现时,我总是注意到一些奇怪的“自然排序顺序”选择,或者更确切地说是错误(或在最好的情况下遗漏)。

通常,特殊字符(空格、破折号、与号、方括号等)无法正确处理。

然后您会发现它们出现在不同的地方,通常可能是:

  • 有些将在大写的“Z”和小写的“a”之间
  • 有些将在“9”和大写的“A”之间
  • 有些会在小写的“z”之后

当人们期望特殊字符全部“组合”在一个地方时,除了空格特殊字符(可能总是第一个字符)。也就是说,要么全部在数字之前,要么全部在数字和字母之间(小写和大写字母一个接一个地“一起”),或者全部在字母之后。

我的结论是,当我开始添加几乎不常见的字符(即带有变音符号或字符,如破折号、感叹号等)时,它们都无法提供一致的顺序。

对自定义实现的研究:

浏览器的原生“自然字符串排序顺序”实现通过 localeCompare()

localeCompare()IE6+ 支持最旧的实现(没有语言环境和选项参数),请参阅http://msdn.microsoft.com/en-us/library/ie/s4esdbwz (v=vs.94) .aspx(向下滚动到 localeCompare( ) 方法)。内置localeCompare()方法在排序方面做得更好,甚至是国际和特殊字符。使用该localeCompare()方法的唯一问题“使用的语言环境和排序顺序完全取决于实现”。换句话说,当使用诸如 stringOne.localeCompare(stringTwo) 之类的 localeCompare 时:Firefox、Safari、Chrome 和 IE 对字符串有不同的排序顺序。

浏览器原生实现的研究:

“字符串自然排序”的难点

实现一个可靠的算法(意思是:一致但也涵盖广泛的字符)是一项非常艰巨的任务。UTF8 包含2000 多个字符涵盖 120 多种脚本(语言)最后,这个任务有一些规范,它被称为“Unicode Collat​​ion Algorithm”,可以在http://www.unicode.org/reports/tr10/找到您可以在我发布的这个问题上找到有关此问题的更多信息https://softwareengineering.stackexchange.com/questions/257286/is-there-any-language-agnostic-specification-for-string-natural-sorting-order

定论

因此,考虑到我遇到的 javascript 自定义实现提供的当前支持水平,我们可能永远不会看到任何接近支持所有这些字符和脚本(语言)的东西。因此,我宁愿使用浏览器的本地 localeCompare() 方法。是的,它确实有跨浏览器不一致的缺点,但基本测试表明它涵盖了更广泛的字符,允许可靠且有意义的排序顺序。

因此,正如 所指出的Shog9,您的问题的答案是:

return item1.attr.localeCompare(item2.attr);

进一步阅读:

感谢 Shog9 的好回答,这让我朝着“正确”的方向发展,我相信

答案(在现代 ECMAScript 中)

list.sort((a, b) => (a.attr > b.attr) - (a.attr < b.attr))

或者

list.sort((a, b) => +(a.attr > b.attr) || -(a.attr < b.attr))

描述

将布尔值转换为数字会产生以下结果:

  • true -> 1
  • false -> 0

考虑三种可能的模式:

  • x 大于 y: (x > y) - (y < x)-> 1 - 0->1
  • x 等于 y: (x > y) - (y < x)-> 0 - 0->0
  • x 小于 y: (x > y) - (y < x)-> 0 - 1->-1

(选择)

  • x 大于 y: +(x > y) || -(x < y)-> 1 || 0->1
  • x 等于 y: +(x > y) || -(x < y)-> 0 || 0->0
  • x 小于 y: +(x > y) || -(x < y)-> 0 || -1->-1

所以这些逻辑相当于典型的排序比较器功能。

if (x == y) {
    return 0;
}
return x > y ? 1 : -1;
添加说明
2021-03-12 01:35:45
正如我对使用此技巧较早答案所评论的那样,通过解释它们的工作原理,可以使纯代码答案更有用。
2021-03-14 01:35:45
您能评论一下这比 localeCompare 好还是坏吗?
2021-03-14 01:35:45
@RanLottemlocaleCompare和标准比较产生不同的结果。你期待哪个? ["A", "b", "C", "d"].sort((a, b) => a.localeCompare(b))按不区分大小写的字母顺序排序,而["A", "b", "C", "d"].sort((a, b) => (a > b) - (a < b))按代码点顺序排序
2021-04-05 01:35:45
比 localeCompare更好,因为 localeCompare 将为不相等的字符串返回 0。具体示例:(至少)有两个不同的“Ö”符号看起来相同,localeCompare 表示它们相同,但它们失败 ===(即使是大写)。所以你漂亮的 UI 代码可能会做一些涉及排序和分组的事情,“Ö”与“Ö”是一样的,但你使用 Map 的后端逻辑将决定这两个 Ö 是不同的,所以结果很糟糕。
2021-04-05 01:35:45

由于字符串可以直接在 javascript 中进行比较,这将完成这项工作

list.sort(function (a, b) {
    return a.attr > b.attr ? 1: -1;
})

排序函数中的减法仅在需要非字母(数字)排序时使用,当然它不适用于字符串

您应该在这里使用 > 或 < 和 ==。所以解决方案是:

list.sort(function(item1, item2) {
    var val1 = item1.attr,
        val2 = item2.attr;
    if (val1 == val2) return 0;
    if (val1 > val2) return 1;
    if (val1 < val2) return -1;
});
附带说明一下,这不会处理字符串与数字的比较。例如:'Z' < 9 (false), 'Z' > 9 (also false??), 'Z' == 9 (also false!!)。JavaScript 中的愚蠢 NaN...
2021-04-06 01:35:45