【问题标题】:Compare two strings with '<' and '>' operators in JavaScript在 JavaScript 中使用 '<' 和 '>' 运算符比较两个字符串
【发布时间】:2019-05-12 05:32:44
【问题描述】:

&gt;&lt; 等比较运算符在输入作为两个字符串值给出时返回 Boolean 值。

我尝试了几个例子:

/* String vs String */
console.log('firstName' < 'lastname'); // true
console.log('firstName' < 'Firstname'); // false
console.log('!firstName' < 'lastname'); // true
console.log('!firstName' < 'Firstname'); // true
console.log('!firstName' < '!Firstname'); // false
console.log('!firstName' < '_!Firstname'); // true
console.log('@!firstName' < '_!Firstname'); // true
console.log('@!firstName' < '2_!Firstname'); // false

/* String vs Number */
console.log('@!firstName' < 2); // false
console.log('@!firstName' < -1); // false

/* String vs Special Numbers */
console.log('@!firstName' < Infinity); // false
console.log('@!firstName' < -Infinity); // false
console.log('@!firstName' < -Infinity + Infinity); // false

/* String vs NaN */
console.log('@!firstName' < NaN); // false
console.log(NaN.toString()); // "NaN"
console.log('@!firstName' < "NaN"); // true

/* String vs Arrays */
console.log('firstName' < [Infinity, -Infinity]); // false
console.log('firstName' < ['Firstname', Infinity, -Infinity]); // false
console.log('firstName' < ['2_Firstname', Infinity, -Infinity]); // false

我真的很想知道 JavaScript 是如何真正评估这些表达式的。在上面的例子中,我觉得这个是最吸引人的一个console.log('@!firstName' &lt; Infinity); // false

所以,我的问题是:

如何使用“大于”和“is 这些场景中 JavaScript 中的小于" 运算符(来自上面的示例):

  1. 字符串与字符串,
  2. 字符串与数字,
  3. 字符串与特殊数字,
  4. 字符串与 NaN,
  5. 字符串与数组

【问题讨论】:

  • 它们的比较使用:ecma-international.org/ecma-262/6.0/…
  • 比较两个字符串时,它会逐个字符地比较它们。如果第一个字符不同,它就不会再看下去了。如果它们相同,则继续下一对字符。如果它到达一个字符串的末尾但没有到达另一个字符串的末尾,则较短的字符串“小于”较长的字符串。如果它们的长度相同且相同,则它们相等。

标签: javascript arrays string


【解决方案1】:

如上所说,正式规范在标准中:http://www.ecma-international.org/ecma-262/7.0/#sec-abstract-relational-comparison,通俗地说逻辑是这样的:

1) 字符串与字符串

将两个字符串拆分为 16 位代码单元并进行数字比较。请注意,代码单元 != 字符,例如"cafè" &lt; "cafè"true(真的)。

2) 字符串与其他原语

将两者都转换为数字。如果其中之一是NaN,则返回false,否则进行数值比较。 +0-0 被认为是相等的,+/-Infinity 比其他任何东西都大/小。

3) 字符串与对象

尝试将对象转换为原语,依次尝试[Symbol.toPrimitive]("number")valueOftoString。如果我们有字符串,则继续 1),否则继续 2)。特别是对于数组,这将调用toString,它与join 相同。

【讨论】:

    【解决方案2】:

    String,String比较基于Unicode排序(a大于A)。

    字符串,数字比较先将字符串转换为数字再进行比较(与无穷大相同)。

    字符串,数组比较先把数组转换成字符串,然后再比较如上。

    Javascript String Comparison
    Javascript Object Comparison

    【讨论】:

      【解决方案3】:

      specification 中描述了要采取的确切步骤,其中具体描述了在比较的一侧(或两侧)为NaN+Infinity-Infinity 的情况下该怎么做。以px &lt; py 为例,less-than operator 调用抽象关系比较算法:

      11.8.5 抽象关系比较算法

      (如果要比较的两个项目都不是字符串,则:)

      令 nx 为调用 ToNumber(px) 的结果。因为 px 和 py 是原始值,所以求值顺序并不重要。

      令 ny 为调用 ToNumber(py) 的结果。

      如果 nx 为 NaN,则返回 undefined。

      如果 ny 为 NaN,则返回 undefined。

      如果 nx 和 ny 是相同的 Number 值,则返回 false。

      如果 nx 为 +0 且 ny 为 -0,则返回 false。

      如果 nx 为 -0 且 ny 为 +0,则返回 false。

      如果 nx 为 +∞,则返回 false。

      如果 ny 为 +∞,则返回 true。

      如果 ny 为 -∞,则返回 false。

      如果 nx 为 -∞,则返回 true。

      如果 nx 的数学值小于 ny 的数学值——注意这些数学值都是有限的,而不是都是零——返回真。否则,返回 false。

      否则,px 和 py 都是字符串

      如果 py 是 px 的前缀,则返回 false。 (如果 q 可以是连接 p 和其他字符串 r 的结果,则字符串值 p 是字符串值 q 的前缀。请注意,任何字符串都是其自身的前缀,因为 r 可能是空字符串。)

      如果px是py的前缀,则返回true。

      令 k 为最小的非负整数,使得 px 中位置 k 处的字符与 py 中位置 k 处的字符不同。 (一定有这样的k,因为两个String都不是另一个的前缀。)

      令 m 为整数,它是 px 中位置 k 处字符的代码单元值。

      令 n 为整数,它是 py 中位置 k 处字符的代码单元值。

      如果 m

      当被比较的两个项目都是字符串时,它实际上会导致每个字符的代码点被比较。例如'firstName' &lt; 'lastname',因为f(102)的字符代码小于l(108)的字符代码。对于'!firstName' &lt; 'Firstname'!(33)的字符代码小于F(70)的字符代码,因此计算结果也为true。有关实现的示例,请参见以下 sn-p:

      function compare(left, right) {
        for (let i = 0; i < left.length; i++) {
          const c1 = left[i].charCodeAt();
          const c2 = right[i].charCodeAt();
          if (c1 !== c2) {
            console.log('Char code comparision:', c1 < c2, '< comparison:', left < right);
            break;
          }
        }
      }
      
      /* String vs String */
      compare('firstName', 'lastname'); // true
      compare('firstName', 'Firstname'); // false
      compare('!firstName', 'lastname'); // true
      compare('!firstName', 'Firstname'); // true
      compare('!firstName', '!Firstname'); // false
      compare('!firstName', '_!Firstname'); // true
      compare('@!firstName', '_!Firstname'); // true
      compare('@!firstName', '2_!Firstname'); // false

      【讨论】:

      • 简而言之,当您将两个字符串与&gt; 进行比较时,它会进行字典比较。松散地说,这意味着它将它们按字母升序排列。它不仅适用于字母表,而且某些字符会出现在字母之前或之后。
      猜你喜欢
      • 1970-01-01
      • 2017-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-25
      • 2013-08-23
      相关资源
      最近更新 更多