快速回顾 JavaScript 的 Array.prototype.sort() 方法
默认数组原型排序()行为
使用 compareFunction 定义排序行为,.sort(function(a, b) { … })
基于嵌套属性对 JSON 进行排序
结论
更新于 2019 年 8 月 28 日
由 Mux 赞助的 DEV 全球展示挑战赛:展示你的项目!
封面图来源:富坚义博漫画《全职猎人》,由本人制作成表情包。<3
在面试中,掌握所选编程语言的基础知识至关重要。这听起来像是常识,但基础知识的缺失会让你显得不够专业。之前我曾有过一次不太光彩的经历:匆匆浏览了MDN上关于JavaScript的Array.prototype.sort()方法的文档,结果却一头雾水。因此,我想用我们之前在本系列文章中获取的同一个JSON对象,来详细讲解一个简单的实现。

整理东西很重要!问问这个人就知道了,他显然知道自己在做什么!
默认数组原型排序()行为
默认情况下,.sort()对 JavaScript 数组进行排序时,会尝试根据字符串的字母顺序或数字的值进行基本的从低到高的排序。但是,默认行为只会比较字符串(仅限首字母)或数字(遇到的第一个数字)的第一个元素。
以下是 MDN 文档中给出的示例:
// sorting strings alphabetically, based on the first letter
var months = ['March', 'Jan', 'Feb', 'Dec'];
months.sort();
console.log(months);
// expected output: Array ["Dec", "Feb", "Jan", "March"]
// sorting integers by their first digit
var array1 = [1, 30, 4, 21, 100000];
array1.sort();
console.log(array1);
// expected output: Array [1, 100000, 21, 30, 4]
可以理解,看到 100000 出现在 1 到 21 之间可能会让你感到意外。幸运的是,JavaScript 提供了一种内置的方法,可以使用compareFunction内部的.sort()!来自定义排序行为。
使用 compareFunction 定义排序行为,.sort(function(a, b) { … })
我们可以通过添加一个名为 `sort` 的匿名函数来改变默认的排序行为compareFunction。我们将其添加到.sort()调用中,并传递参数 `a` 和`b`a来b表示数组的元素。
例如,我们可以比较整数的整个值,而不是只比较它的第一位数字,a并b根据这个值进行排序。
再次改编自 MDN 文档:
// sorting integers by their value
var array1 = [1, 30, 4, 21, 100000];
array1.sort(function(a, b) { // this anonymous function is the compareFunction
if (a < b) { // now the entire values of a & b are compared
return -1;
};
if (a > b) {
return 1;
};
// a must be equal to b, no change to index
return 0;
});
console.log(array1);
// expected output: Array [1, 4, 21, 30, 100000]
太好了!现在,通过显式地比较a 和 b的完整值,而不是仅仅比较它们的第一位数字,我们就得到了我们期望的数值排序结果。ab
请注意,匿名函数compareFunction比较特殊,因为它只寻找负数(-1)、零(0)或正数(1)的返回值:
Negative => lower index
Zero => no change
Positive => higher index
因此,我们可以创建任何我们希望最终返回负值/零值/正值的条件。
基于嵌套属性对 JSON 进行排序
简而言之:将嵌套属性分配给变量,以便在比较逻辑中轻松使用!
让我们来看一个更复杂的例子:按属性字母顺序对来自https://www.reddit.com/r/popular.json"title"的 JSON 进行排序。
提醒一下,以下是我们将要排序的 JSON 数据,具体排序依据是data.children数组中的属性:
我们将继续使用本系列前一篇文章中探讨过的node-fetch 包:
const url = "https://www.reddit.com/r/popular.json"
// use the node-fetch package to retrieve JSON from the URL above
const fetch = require('node-fetch');
let settings = {
method: "Get"
};
fetch(url, settings)
.then(res => res.json())
.then((json) => {
sortJson(json);
});
在我们的函数内部sortJson(),我们将使用以下步骤:
- 我们选择数组中每个对象内部要读取的属性
data.children,通过以下方式访问data.children[i].data[property]: - 我们定义了一个比较和 的
compareFunction属性的函数,使用我们定义的。我们将嵌套值分配给易于访问的变量和。ab”property”property1property2 - 比较 `
property1and` 和 `property2.`。与往常一样,这些比较会返回负值 (-1)、零值 (0) 或正值 (1)。原始数组将根据该属性重新排序。
以下是我们的函数,它使用该”title”属性按点赞数排序:
// sort Array json.data.children alphabetically by "title"
function sortJson(json) {
// you can easily change this to any property, such as “ups” or “author_fullname"
let property = "title";
json.data.children.sort(function(a, b) {
// create new variables to easily access nested data for sorting
let propertyA = a.data[property];
let propertyB = b.data[property];
if (propertyA < propertyB) { // checks for a “lower” alphabetical order
return -1
};
if (propertyA > propertyB) { // checks for a “higher” alphabetical order
return 1
};
return 0 // if titles are equal
});
// First 3 Objects in Array json.data.children BEFORE sort():
// [0].data.title: What do you NEVER f*** with?
// [1].data.title: [Game Thread] Florida vs. Miami (7:00PM ET)
// [2].data.title: 🎉 100.000.000 SUBSCRIBERS 🎉
// First 3 Objects in Array json.data.children AFTER sort():
// [0].data.title: 'Like you've been fired from your job': YouTubers have lost thousands of dollars after their channels were mistakenly demonetized for months
// [1].data.title: Disney+ episodes will release on a weekly basis, instead of the all at once “binge” model
// [2].data.title: Employee spits in food for Instagram likes
请注意,我们的输出遵循标准的 JavaScript 字符串字母排序规则,例如撇号'位于字母D之前。
结论
排序是任何编程语言中必不可少的功能,因此在遇到技术难题之前,务必练习排序!此外,对于 JavaScript 和 Ruby 等语言,一定要深入了解排序方法的底层实现,因为你可能需要创建一些自定义的排序功能。
和往常一样,花点时间熟悉一下 MDN 文档也无妨,以防你需要快速查阅:Array.prototype.sort() 的 MDN 文档
欢迎在下方留言分享其他排序技巧或窍门!
更新于 2019 年 8 月 28 日
Phil Nash刚刚发表了一篇精彩的文章,详细分析了JavaScript中的陷阱和不一致之处Array.prototype.sort()。具体来说,他涵盖了两个与本文内容相辅相成的重要主题:
- 如何处理空值(强制转换为字符串“null”或整数0)
- 如何处理未定义对象/具有未定义值的对象
