【问题标题】:In JS, can you rely on comparing strings with the ">" and "<" operators?在 JS 中,你可以依靠 ">" 和 "<" 操作符来比较字符串吗?
【发布时间】:2018-01-27 08:18:11
【问题描述】:

我正在构建一个抽象表,表中的每一列可以包含所有数字或所有字符串。每一列都应该可以通过单击列标题进行排序。

目前我正在使用 JS native sort 并传递一个 compareFunction:

const rows = [
  {name: 'Adam', age: 27, rank: 3},
  {name: 'Zeek', age: 31, rank: 1},
  {name: 'Nancy', age: 45, rank: 4},
  {name: 'Gramps', age: 102, rank: 2},
]

const compareFn = (x, y) => {
  const sortDirValue = this.state.sortDirection === 'DESC' ? 1 : -1
  if (x[this.state.sortBy] === y[this.state.sortBy]) return 0
  return x[this.state.sortBy] < y[this.state.sortBy] ? sortDirValue : -sortDirValue
}

this.state = {
  sortBy: 'name',
  sortDirection: 'ASC'
}
rows.sort(compareFn)
console.log('---- Sorted by alphabetical name ----')
console.log(rows)

this.state = {
  sortBy: 'age',
  sortDirection: 'DESC'
}
rows.sort(compareFn)
console.log('---- Sorted by descending age ----')
console.log(rows)

到目前为止,在我尝试过的所有测试用例中,这似乎都有效。但是,我知道 JS 对排序可能很挑剔,比如开箱即用的sort() 将如何sort arrays of numbers alphabetically

我可以依靠上述方法对数字和字符串进行一致的正确排序吗?如果不能,有哪些数据不会以这种方式正确排序的示例。

【问题讨论】:

  • @CumuloNimbus 不,您的比较函数认为相等的字符串是不同的。
  • @melpomene 现在它应该处理相等的情况,感谢您的彻底

标签: javascript


【解决方案1】:

,不能依赖&gt;/&lt; 运算符的字母排序。数据无法以这种方式正确排序的最突出示例是混合使用大小写字符。

其他答案是有效的,因为使用 localeCompare 是比较字符串的方法。但是,我发现数字以及字符串和数字的混合也可以通过这种方式有效地进行比较。

x.localeCompare(y, 'kn', { numeric: true })

通过使用numeric option localeCompare 提供的服务,我能够实现更强大的排序,同时还避免需要分支条件逻辑来处理stringnumber 的每个情况。

const rows = [
  {name: 'Adam', age: 27, rank: 3, thing: 19},
  {name: 'Zeek', age: 31, rank: 1, thing: 'wut dis'},
  {name: 'Nancy', age: 45, rank: 4, thing: '$dolla'},
  {name: 'Gramps', age: 102, rank: 2, thing: 2},
]

const compareFn = (x, y) => {
  const xData = x[this.state.sortBy].toString()
  const yData = y[this.state.sortBy].toString()
  if (this.state.sortDirection !== 'DESC') {
    return xData.localeCompare(yData, 'kn', { numeric: true })
  } else {
    return yData.localeCompare(xData, 'kn', { numeric: true })
  }
}

this.state = {
  sortBy: 'name',
  sortDirection: 'ASC'
}
rows.sort(compareFn)
console.log('---- Sorted by alphabetical name ----')
console.log(rows)

this.state = {
  sortBy: 'age',
  sortDirection: 'DESC'
}
rows.sort(compareFn)
console.log('---- Sorted by descending age ----')
console.log(rows)

this.state = {
  sortBy: 'thing',
  sortDirection: 'ASC'
}
rows.sort(compareFn)
console.log('---- Sorted by ascending thing ----')
console.log(rows)

【讨论】:

    【解决方案2】:

    虽然您可以依靠使用&gt;&lt; 运算符比较字符串,但我建议您改用String#localeCompare

    正如ECMAScript specification 所述,localeCompare 函数将在比较字符串之前进行一些检查。

    你也可以在原文ECMAScript specification中找到更多解释:

    此函数旨在依赖于任何可用的语言敏感比较功能 从宿主环境到ECMAScript环境,并根据规则进行比较 宿主环境的当前语言环境。强烈建议此函数处理以下字符串 根据 Unicode 标准,它们在规范上是相同的(换句话说,比较 就好像它们都先被转换为规范化形式 C 或 D 一样)。

    更新后的代码应该是这样的:

    const compareFn = (x, y) => {
      if (this.state.sortDirection === 'DESC') {
        return x[this.state.sortByKey].localeCompare(y[this.state.sortByKey])
      } else {
        return y[this.state.sortByKey].localeCompare(x[this.state.sortByKey])
      }
    }
    rows.sort(compareFn)
    

    【讨论】:

    • 原因是什么?只是感兴趣,我也不知道。
    • 有趣,你有没有具体的例子说明“
    【解决方案3】:

    我想说,在 JS 中比较字符串的最好方法是localeCompare() 方法。

    first_string.localeCompare(second_string);
    /* Expected results:
     0:  exact match
    -1:  first_string< second_string
     1:  first_string> second_string
     */
    

    如果您需要其他信息,您应该阅读一些文档herehere


    更新

    .localeCompare() 允许您可能希望忽略字符串中的某些差异(例如标点符号或变音符号或大小写)并仍然允许它们进行相同的比较,或者您希望在决定哪个字符串时忽略某些差异在另一个之前。而且,它提供了许多选项来控制使用或不使用哪些比较功能。

    如果您阅读MDN documentation 中的string.prototype.localeCompare(),您会看到一大堆可以传入的选项来指定比较的工作方式。 在没有特殊字符且大小写相同的普通 ascii 字符串上,您不太可能看到差异,但开始涉及变音符号或大小写问题,localCompare() 具有更多功能和控制比较的更多选项。

    一些可用于控制比较的选项: - 数字排序规则 - 变音敏感性 - 忽略标点符号的能力 - 案例优先 - 控制是先比较大写还是小写

    Morover,localeCompare() 返回一个值(负数、0 或正数),即 perfectly aligned to use with a .sort() 回调。

    【讨论】:

      【解决方案4】:

      它将比较字符串,但具体的 unicode 值可能与预期的行为不同。例如,无论字母顺序如何,大写字母的值都将低于小写字母。如果您要使用它,请记住顺序是 { / } / |大于小写字母、大于 CAPITAL、大于数字、大于大多数符号 (!",)。

      【讨论】:

        【解决方案5】:

        要直接回答您的问题 - 是的,您可以使用您的方法进行一致的排序。使用 Unicode 值根据标准字典顺序比较字符串。 见:

        【讨论】:

        • 您绝对不能依靠这种方法对字符串进行一致的排序!不要让 Ivaylo 欺骗你
        • @CumoloNimbus,您问是否可以依赖这种方法的一致性。使用 '' 进行排序将是一致的,但可能不是您在场景中需要的。使用localeCompare 可以更好地控制比较字符串的方式。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-02-14
        • 2013-03-24
        • 1970-01-01
        • 2023-03-17
        • 2020-11-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多