js中数组sort方法的使用和模拟实现
一、定义
sort方法是对数组的元素进行排序,并返回对相同数组的引用。
二、语法
sort() // 无参数直接调用
sort(compareFn) // 传一个回调函数
三、参数
compareFn 可选
传入的回调函数根据返回值决定排序的顺序。
a compareFn函数的第一个用于比较的元素。是用于的排序的数组中的元素。
b compareFn函数的第二个用于比较的元素。是用于的排序的数组中的元素。
四、返回值
返回经过排序的原始数组的引用,也就是说原数组同时也会改变。
五、详细描述
sort方法可以对数组进行排序,并且返回原数组的引用(也就是说原数组同时会改变)。
sort方法的参数是可选的,如果不传的时候会将数组的元素转为字符串,然后根据每个字符的 Unicode 码位值进行排序。
如果传递了排序规则函数compareFn那么数组每一项非undefined的元素将会按照compareFn函数的返回值进行排序。(所有的 undefined 元素都会被排序到数组的末尾,并且不调用 compareFn)。
compareFn函数里面有两个参数都是原数组中的元素,他们的排序规则如下:
- 如果compareFn返回值大于0,那么 a 排在 b 后。
- 如果compareFn返回值等于0,那么就是保持a, b现在顺序不变。
- 如果compareFn返回值小于0,那么 b 排在 a 后。
compareFn函数的规则还有很多详细了解可以参考这篇文章https://zhuanlan.zhihu.com/p/379301236。
我们使用时只需要知道compareFn(a, b)的返回值 为a - b 代表了升序,而b - a 代表了降序。
六、使用示例
不传入compareFn排序参数
// 不传入compareFn参数
const list1 = [1, 100, 10, 62, 8];
const list2 = ['blue', 'yellow', 'red', 'green'];
const list3 = [1, 100, 10, 62, 8, '50', '1000'];
const list4 = [{ num: 4 }, { num: 10 }, { num: 62 }, { num: 100 }];
console.log(list1.sort()); // [1, 10, 100, 62, 8]
console.log(list2.sort()); // ['blue', 'green', 'red', 'yellow']
console.log(list3.sort()); // [1, 10, 100, '1000', '50', 62, 8]
console.log(list4.sort()); // [{ num: 4 }, { num: 10 }, { num: 62 }, { num: 100 }];
传入compareFn排序参数
// 传入compareFn参数
const list1 = [1, 100, 10, 62, 8];
const list2 = ['blue', 'yellow', 'red', 'green'];
const list3 = [1, 100, 10, 62, 8, '50', '1000'];
const list4 = [{ num: 4 }, { num: 10 }, { num: 62 }, { num: 100 }];
// 传入升序参数
const compareFn1 = (a, b) => a - b;
console.log(list1.sort(compareFn1)); // [1, 8, 10, 62, 100]
console.log(list2.sort(compareFn1)); // ['blue', 'yellow', 'red', 'green']
console.log(list3.sort(compareFn1)); // [1, 8, 10, '50', 62, 100, '1000']
// 数组对象需要使用里面的一项值来判断
console.log(list4.sort((a, b) => a.num - b.num)); // [{ num: 4 }, { num: 10 }, { num: 62 }, { num: 100 }]
// 传入降序参数
const compareFn2 = (a, b) => b - a;
console.log(list1.sort(compareFn2)); // [100, 62, 10, 8, 1]
console.log(list2.sort(compareFn2)); // ['blue', 'yellow', 'red', 'green']
console.log(list3.sort(compareFn2)); // ['1000', 100, 62, '50', 10, 8, 1]
// 数组对象需要使用里面的一项值来判断
console.log(list4.sort((a, b) => b.num - a.num)); // [{ num: 100 }, { num: 62 }, { num: 10 }, { num: 4 }]
七、模拟实现
Array.prototype.mySort = function (compareFn) {
if (compareFn && typeof compareFn !== 'function')
throw new Error('compareFn必须是函数或者undefined');
// 只有一个数据或者空数组时直接返回
if (this.length < 2) return this;
// 不传参数时
if (!compareFn) {
// 使用冒泡排序
for (let index = 0; index < this.length; index++) {
for (let j = 0; j < this.length - 1 - index; j++) {
// 转换为字符串升序比较
if (String(this[j + 1]) < String(this[j])) {
const exchange = this[j];
this[j] = this[j + 1];
this[j + 1] = exchange;
}
}
}
return this;
}
// 快速排序定义
const quickSort = function (arr, left, right) {
if (left >= right) return;
const pivotValue = arr[right];
let partitionIndex = left;
for (let i = left; i < right; i++) {
const result = compareFn(arr[i], pivotValue);
// 根据返回结果处理数组的顺序
if (result < 0 || isNaN(result)) {
[arr[i], arr[partitionIndex]] = [arr[partitionIndex], arr[i]];
partitionIndex++;
}
}
[arr[right], arr[partitionIndex]] = [arr[partitionIndex], arr[right]];
quickSort(arr, left, partitionIndex - 1);
quickSort(arr, partitionIndex + 1, right);
};
// 传入compareFn参数时调用快速排序算法对新数组进行排序
quickSort(this, 0, this.length - 1);
return this;
};
八、验证
不传入compareFn排序参数验证文章来源:https://uudwc.com/A/AZm1E
// 传入compareFn参数
const list1 = [1, 100, 10, 62, 8];
const list2 = ['blue', 'yellow', 'red', 'green'];
const list3 = [1, 100, 10, 62, 8, '50', '1000'];
const list4 = [{ num: 4 }, { num: 10 }, { num: 62 }, { num: 100 }];
console.log(list1.mySort()); // [1, 10, 100, 62, 8]
console.log(list2.mySort()); // ['blue', 'green', 'red', 'yellow']
console.log(list3.mySort()); // [1, 10, 100, '1000', '50', 62, 8]
console.log(list4.mySort()); // [{ num: 4 }, { num: 10 }, { num: 62 }, { num: 100 }];
传入compareFn排序参数验证文章来源地址https://uudwc.com/A/AZm1E
// 传入compareFn参数
const list1 = [1, 100, 10, 62, 8];
const list2 = ['blue', 'yellow', 'red', 'green'];
const list3 = [1, 100, 10, 62, 8, '50', '1000'];
const list4 = [{ num: 4 }, { num: 10 }, { num: 62 }, { num: 100 }];
// // 传入升序参数
const compareFn1 = (a, b) => a - b;
console.log(list1.mySort(compareFn1)); // [1, 8, 10, 62, 100]
console.log(list2.mySort(compareFn1)); // ['blue', 'yellow', 'red', 'green']
console.log(list3.mySort(compareFn1)); // [1, 8, 10, '50', 62, 100, '1000']
// 数组对象需要使用里面的一项值来判断
console.log(list4.mySort((a, b) => a.num - b.num)); // [{ num: 4 }, { num: 10 }, { num: 62 }, { num: 100 }]
// // 传入降序参数
const compareFn2 = (a, b) => b - a;
console.log(list1.mySort(compareFn2)); // [100, 62, 10, 8, 1]
console.log(list2.mySort(compareFn2)); // ['blue', 'yellow', 'red', 'green']
console.log(list3.mySort(compareFn2)); // ['1000', 100, 62, '50', 10, 8, 1]
// 数组对象需要使用里面的一项值来判断
console.log(list4.mySort((a, b) => b.num - a.num)); // [{ num: 100 }, { num: 62 }, { num: 10 }, { num: 4 }]