使用 JavaScript 的排序方法对字符串数组排序

在 ** Array 原型中可用的 `sort' 方法允许您对数组的元素进行排序. 它接受一项可选的回调函数,您可以使用它来根据您的特定需求定制排序机制。

<$>[注] 对于数组,请参阅我们之前的帖子 排序数组

排序字符串可以因为种类方法是如何工作的而得到相当的舆论。

首先,ECMAScript标准不指定特定的分类算法,一切都取决于每个浏览器供应商。

其次,外壳在排序时发挥着至关重要的作用。为了排序工作,必须有事物的序列安排,这可以通过数字获得 - 数字自然是序列的( 1, 2, 3, 4...).当串被比较时,它们被转换为其等同的 Unicode值 - 这是不可思议的数字,然后以序列排序,默认顺序上升。

字符的 Unicode 值

要抓住每个字符的Unicode值 - 较低或较高,我们使用charCodeAt字符串方法访问指定的字符索引的字符代码。

留在我身边

我们将通过创建实用函数来开始,这有助于获取字符以及字符的 ** unicode 值。

 1// get Unicode values of character items in an array
 2function getCharactersUnicodeValue(characters) {
 3  const unicodeChart = new Map();
 4  characters.forEach(character => {
 5    unicodeChart.set(
 6      character,
 7      character.charCodeAt(character.indexOf(character))
 8    );
 9  });
10  console.table(unicodeChart);
11}
12
13// get unicode values of a single character
14function getCharacterUnicodeValue(character) {
15  const value = character.charCodeAt(character.indexOf(character));
16  console.log(value);
17}

請參閱此處的「地圖」。


我们将称之为实用功能,如:

1getCharactersUnicodeValue("ABCDEFabcdef".split("")); // array of characters: [ 'A', 'B', 'C', 'D', 'E', 'F', 'a', 'b', 'c', 'd', 'e', 'f' ]
2// Result: {character → Unicode Value}
3// { A → 65, B → 66, C → 67, D → 68, E → 69, F → 70, a → 97, b → 98, c → 99, d → 100, e → 101, f → 102 }
4
5getCharacterUnicodeValue("A");
6// Result: {character → Unicode Value}
7// { A → 65 }

这里还有另一个例子:

1const crocodilian = "crOCoDiliaN".split(""); // array of characters i.e [ 'c', 'r', 'O', 'C', 'o', 'D', 'i', 'l', 'i', 'a', 'N' ]
2
3getCharactersUnicodeValue(crocodilian);
4
5// Result: {character → Unicode Value}
6// { c → 99, r → 114, O → 79, C → 67, o → 111, D → 68, i → 105, l → 108, a → 97, N → 78 }

请注意,UPPERCASE 字符在下面的字符之前出现,并且它们会以序列出现。 这些字符被分类为: `[‘蛋’, ‘尾巴’, ‘蛋’]。 请注意,‘尾巴’是如何在‘蛋’之前出现的? 这是因为:

1getCharactersUnicodeValue(["Eggs", "Tail", "eggs"]);
2
3// Result: {character → Unicode Value}
4// { Eggs → 69, Tail → 84, eggs → 101 }
5// 84 (T) of Tail comes numerically before 101 (e) of eggs

TL;DR:当一个字符串只用相同的案例(所有上方或所有下方)形成时,分类很容易。

混合案例串的分类

大多数时候,我们会希望我们的混合案例字符串的 ** 数组** 进行排序,而不论是 ** 案例**。

const things = [ 'nest', 'Eggs', 'bite', 'gator', 'caYman', 'Grip', 'grips', 'Jaw', 'crocodilian', 'Bayou' ];

最终应将其分为:

【【‘Bayou’,‘bite’,‘caYman’,‘crocodilian’,‘Eggs’,‘gator’,‘Grip’,‘grips’,‘Jaw’,‘nest’】

而不是:

[ 'Bayou', 'Eggs', 'Grip', 'Jaw', 'bite', 'caYman', 'crocodilian', 'gator', 'grips', 'nest' ]

尝试一:没有比较函数

没有比较函数来调用排序方法不会起作用:

1things.sort();
2
3// ['Bayou', 'Eggs', 'Grip', 'Jaw', 'bite', 'caYman', 'crocodilian', 'gator', 'grips', 'nest']

尝试二:使用比较函数

1function sortThings(a, b) {
2  if (a > b) {
3    return 1;
4  } else if (a < b) {
5    return -1;
6  } else if (a === b) {
7    return 0;
8  }
9}

然后使用比较函数进行排序:

1things.sort(sortThings);
2
3// [ 'Bayou', 'Eggs', 'Grip', 'Jaw', 'bite', 'caYman', 'crocodilian', 'gator', 'grips', 'nest' ]

然而,它并不起作用,事实上,我们可能还没有写出一个比较函数。

尝试三:具有比较函数和常见案例

问题是,排序仍然使用了事物数组元素的默认混合案例,我们需要做的就是将案例转换为常见案例 - 无论是 lowercase 还是 UPPERCASE。

 1function sortThings(a, b) {
 2  a = a.toLowerCase();
 3  b = b.toLowerCase();
 4
 5  if (a > b) {
 6    return 1;
 7  } else if (a < b) {
 8    return -1;
 9  } else if (a === b) {
10    return 0;
11  }
12}

或者,使用 Ternary 操作员:

1function sortThings(a, b) {
2  a = a.toLowerCase();
3  b = b.toLowerCase();
4
5  return a > b ? -1 : b > a ? 1 : 0;
6}

然后再使用比较函数进行排序:

1things.sort(sortThings);
2
3// ['Bayou', 'bite', 'caYman', 'crocodilian', 'Eggs', 'gator', 'Grip', 'grips', 'Jaw', 'nest' 'eggz']

<$>[注] 现在它工作了! <$>

但等待,还有更多

虽然浏览器供应商有其特定的排序算法,但我们应该熟悉一些技术。排序是根据charCodeAt(index)进行的。在两个比较项目几乎相似的场景中,他们的charCodeAt(index)正在连续进行比较。

卵子卵子为例:

没有转换为下方,‘Eggz’将在‘eggs’之前出现,因为‘E → 69’的Unicode值在‘e → 101’之前出现 。

跑步:

1['Eggz', 'eggs'].sort(sortThings);
2
3// ['eggs', 'Eggz']

正确地排序,最后的字符 `s → 115 和 z → 122' 是确定性字符。

检查过程如下:

[e → 101 ]ggs 和 [e → 101]ggz / 101 === 101,我们移动到下一个字符

  • e[g → 103]gs 和 e[g → 103]gz / 103 === 103,我们移动到下一个字符
  • 例如[g → 103]s 和 eg[g → 103]z / 103 === 103,我们移动到下一个字符
  • 鸡蛋(s → 115) 和鸡蛋(z → 122) /显然, 115 来之前 122.

是的,这决定了对决!

降级命令

如果您需要以下降顺序排序,只需在比较函数中以返回 -1 来交换返回 1 :

 1function sortThings(a, b) {
 2  a = a.toLowerCase();
 3  b = b.toLowerCase();
 4  if (a > b) {
 5    return -1;
 6  } else if (b > a) {
 7    return 1;
 8  } else {
 9    return 0;
10  }
11}

或:

1function sortThings(a, b) {
2  a = a.toLowerCase();
3  b = b.toLowerCase();
4  return a > b ? -1 : b > a ? 1 : 0;
5}

或者只是用反向数组方法逆转排序的数组,显然将数组逆转到相反的序列:

1things.sort(sortThings).reverse();

替代方案:使用 LocalCompare

虽然 localeCompare字符串方法可以比较字符,而不论使用的案例,它是一个字符串方法,所以它不能直接在一个数组上使用。

1things.sort((a, b) => a.localeCompare(b));
2
3// [ 'Bayou', 'bite', 'caYman', 'crocodilian', 'Eggs', 'gator', 'Grip', 'grips', 'Jaw', 'nest' ]

代码一眼

 1const things = [
 2  "nest",
 3  "Eggs",
 4  "bite",
 5  "gator",
 6  "caYman",
 7  "Grip",
 8  "grips",
 9  "Jaw",
10  "crocodilian",
11  "Bayou"
12];
13console.log(`unsorted: ${things.join(", ")}`);
14
15function sortThings(a, b) {
16  a = a.toLowerCase();
17  b = b.toLowerCase();
18  return a > b ? 1 : b > a ? -1 : 0;
19}
20
21console.log(`sorted:  ${things.sort(sortThings).join(", ")}`);

记住,继续排序,世界需要它。

Published At
Categories with 技术
Tagged with
comments powered by Disqus