该函数可以对数组arr进行排序。排序的依据是通过函数参数(从第二个参数开始)指定的多个排序条件。这些条件可以是对象、函数或字符串。
function sort(arr) {
// 收集排序条件
var sortConditions = [];
for (var i = 1; i < arguments.length; i++) {
sortConditions.push(arguments[i]);
}
// 自定义排序函数
arr.sort(function (a, b) {
if (a === null) return -1; // 如果 a 是 null,a 排在前面
if (b === null) return 1; // 如果 b 是 null,b 排在后面
// 遍历所有排序条件
for (var j = 0; j < sortConditions.length; j++) {
var condition = sortConditions[j];
var sortDirection = 1; // 默认升序
// 检查条件类型
if (typeof condition === 'object') {
// 如果条件是对象,检查其 type 属性
if (typeof condition.type === 'number') {
sortDirection = condition.type; // 使用给定的排序方向
} else if (condition.type && condition.type.toLowerCase() === 'desc') {
sortDirection = -1; // 降序
}
// 使用对象的 name 属性作为排序键
condition = condition.name;
} else if (typeof condition === 'function') {
// 如果条件是函数,直接调用并返回结果
var result = condition(a, b);
if (result !== 0) {
return result * sortDirection; // 应用排序方向
}
// 如果函数返回 0,继续下一个条件
continue;
} else if (typeof condition === 'string') {
// 如果条件是字符串,检查是否包含方向指示
var parts = condition.split(':');
condition = parts[0]; // 排序键
if (parts[1] && parts[1].toLowerCase() === 'desc') {
sortDirection = -1; // 降序
}
}
// 如果 a 和 b 都是对象,则按条件指定的属性进行比较
if (typeof a === 'object' && typeof b === 'object') {
var keys = condition.split('.');
var aValue = a;
var bValue = b;
for (var k = 0; k < keys.length; k++) {
if (aValue && aValue.hasOwnProperty(keys[k])) {
aValue = aValue[keys[k]];
} else {
aValue = undefined; // 如果属性不存在,设为 undefined
}
if (bValue && bValue.hasOwnProperty(keys[k])) {
bValue = bValue[keys[k]];
} else {
bValue = undefined; // 如果属性不存在,设为 undefined
}
}
// 比较属性值
if (aValue < bValue) return -sortDirection; // a 应该排在前面
if (aValue > bValue) return sortDirection; // b 应该排在前面
} else {
// 如果 a 和 b 不是对象,则直接比较它们
if (a < b) return -sortDirection; // a 应该排在前面
if (a > b) return sortDirection; // b 应该排在前面
}
}
// 所有条件都相同,返回 0
return 0;
});
// 返回排序后的数组
return arr;
}
原数组:
var a=[{name:"xpp", lvl:90, power:20, age:15},{name:"xtpp", lvl:9, power:25, age:15},{name:"tpp", lvl:50, power:18, age:10},{name:"tpp", lvl:50, power:38, age:10},{name:"tpp", lvl:9, power:20, age:10}]
对数组a,先按等级降序排列,再按战力升序排列
方法一:
sort(a, "lvl:desc","power:asc")
方法二:
sort(a, {name:"lvl", type:"desc"},{name:"power", type:"asc"})
排序列结果:
[{"name":"xpp","lvl":90,"power":20,"age":15},{"name":"tpp","lvl":50,"power":18,"age":10},{"name":"tpp","lvl":50,"power":38,"age":10},{"name":"tpp","lvl":9,"power":20,"age":10},{"name":"xtpp","lvl":9,"power":25,"age":15}]
/**
* 对数组进行排序的通用方法,支持多字段排序。
*
* @param arr 要排序的数组。
* @param sorters 排序规则,可以是函数、字符串(格式为 "字段名:desc" 表示降序)、或带有字段和排序类型的对象。
* 例如:sorters: ['age', { name: 'name', type: 'desc' },“power:asc”] 表示先按 age 升序,再按 name 降序排序,最后按power升序
*
* @returns 排序后的新数组。
*/
sort<T>(arr: T[], ...sorters: Array<((a: T, b: T) => number) | string | { name: string, type?: number | 'desc' }>): T[] {
return arr.sort((a: T, b: T): number => {
// 空值处理:null 始终排在最后
if (a === null) return -1;
if (b === null) return 1;
for (const sorter of sorters) {
let compareValue = 1; // 默认升序
let fieldPath: string;
// 如果是自定义比较函数
if (typeof sorter === 'function') {
const result = sorter(a, b);
if (result !== 0) return result; // 比较结果不为0则直接返回
continue; // 否则继续下一个排序条件
}
// 处理对象类型的排序器 { name: '字段名', type: 'desc' }
if (typeof sorter === 'object' && sorter !== null) {
if (typeof sorter.type === 'number') {
compareValue = sorter.type; // 自定义数值类型
} else if (sorter.type?.toLowerCase() === 'desc') {
compareValue = -1; // 降序排列
}
fieldPath = sorter.name as string;
}
// 处理字符串类型的排序器,如 "字段名:desc"
else if (typeof sorter === 'string') {
const parts = sorter.split(':');
fieldPath = parts[0];
if (parts.length > 1 && parts[1].toLowerCase() === 'desc') {
compareValue = -1; // 降序排列
}
}
// 获取嵌套属性值,例如 a.field.subField
const getNestedValue = (obj: any, path: string): any => {
return path.split('.').reduce((current, key) => current?.[key], obj);
};
const aVal = getNestedValue(a, fieldPath);
const bVal = getNestedValue(b, fieldPath);
// 实际比较逻辑
if (aVal < bVal) return compareValue <= 0 ? 1 : -1; // 升序或降序
if (aVal > bVal) return compareValue <= 0 ? -1 : 1;
}
return 0; // 所有排序字段相等时返回0
});
}
上面的这个要测试