在 ** 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(", ")}`);
记住,继续排序,世界需要它。