为什么我的自定义 sort() 函数在 JavaScript 中不被接受?
Why does my custom sort() function cannot be accepted in JavaScript?
我尝试升级 JavaScript 当前的自定义排序功能以创建新的排序顺序
例如(1, 2, 3, 4,..., !@#$%^=+, a, A, b, B, c, C)
function getSortOrder(prop) {
return function (a, b) {
if (isSpecialChar(a[prop], 0) || isSpecialChar(b[prop], 0)) {
return sortData(a[prop], b[prop]);
}
if (isNumeric(a[prop], 0) == "number" || isNumeric(b[prop], 0) == "number") {
return getSortNumeric(a[prop], b[prop]);
}
if (isLetter(a[prop], 0) || isLetter(b[prop], 0)) {
return getSortLetter(a[prop], b[prop]);
}
};
}
function getSortLetter(a, b) {
if ((a.charAt(0) === getLowerCase(a, 0)) && (b.charAt(0) === getUpperCase(b, 0))) {
return sortData(a, b);
}
return sortData(a, b);
}
function getSortNumeric(a, b) {
if (typeof a[prop] == "number") {
return (a[prop] - b[prop]);
} else {
return ((a[prop] < b[prop]) ? -1 : ((a[prop] > b[prop]) ? 1 : 0));
}
}
function sortData(a, b) {
if (a.toLowerCase() < b.toLowerCase()) {
return -1;
} else if (a.toLowerCase() > b.toLowerCase()) {
return 1;
} else {
return 0;
}
}
/**
* Function that is used for the ascending order of number
*
*/
const sortNumberData = (a, b) => a.localeCompare(b, 'en', { numeric: true })
// to check if the data has numeric
function isNumeric(str, index) {
let x = /^[0-9]$/.test(str.charAt(index));
console.log(str, x);
return x;
}
// to determine if the data has neither numeric or letter
function isSpecialChar(str, index) {
return !isNumeric(str, index) && !isLetter(str, index);
}
// to specify the order of letter e.g. (jane doe, Jane Doe, john doe, John doe)
function isLetter(str, index) {
return str.charAt(index).length === 1 && str.match(/[a-z]/i);
}
function getLowerCase(str, index) {
return str.charAt(index).toLowerCase();
}
function getUpperCase(str, index) {
return str.charAt(index).toUpperCase();
}
Json 值的预期结果:
用户列表:
123管理员
321用户
!testAdmin
#adminData
无名氏
简·史密斯
约翰·多伊
李四
Json 值的当前结果:
用户列表:
!testAdmin
#adminData
123管理员
321用户
简·史密斯
无名氏
约翰·多伊
它仍然遵循 Ascii 默认排序顺序。
对于想要的订单,您可以使用 string/object 的蛮力方法。
此方法迭代每对字符串并通过获取顺序检查任何字符,直到找到不同的字符。
const
chars = ' 0123456789!@#$%^=+abcdefghijklmnopqrstuvwxyz',
order = Object.fromEntries(Array.from(chars, ((c, i) => [c, i + 1]))),
sort = (a, b) => {
for (let i = 0, l = Math.min(a.length, b.length); i < l; i++) {
const r = order[a[i].toLowerCase()] - order[b[i].toLowerCase()];
if (r) return r;
}
return a.length - b.length;
},
sortBy = (fn, k) => (a, b) => fn(a[k], b[k]),
data = [{ name: 'abcd' }, { name: 'abc' }, { name: 'John Doe' }, { name: '!testAdmin' }, { name: '#adminData' }, { name: '123Admin' }, { name: '321user' }, { name: 'Jane Smith' }, { name: 'jane doe' }, { name: 'john doe' }];
data.sort(sortBy(sort, 'name'));
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz 建议的方法更简洁,但您的原始代码存在以下问题:
您的 isLetter
函数没有 return 正确的结果。使用下面的 RegExp.test
方法可以解决这个问题:
function isLetter(str, index) {
return str.charAt(index).length === 1 && /^[a-z]/i.test(str);
}
您的 getSortOrder
函数在比较属于不同组(特殊字符/数字/字母)的字符时也无法正确处理排序。要解决这个问题,您可以更改该函数以区分角色何时属于同一组以及何时属于不同组:
function getSortOrder(a, b) {
if (isNumeric(a, 0) && isNumeric(b, 0)) return sortData(a, b);
if (isSpecialChar(a, 0) && isSpecialChar(b, 0)) return sortData(a, b);
if (isLetter(a, 0) && isLetter(b, 0)) return sortData(a, b);
if (isNumeric(a, 0)) return -1;
if (isLetter(a, 0)) return 1;
if (isSpecialChar(a, 0)) {
if (isNumeric(b, 0)) return 1;
return -1;
}
}
最后,sortData
函数不区分大小写。它需要做这样的事情:
function sortData(a, b) {
const aLower = a[0].toLowerCase();
const bLower = b[0].toLowerCase();
if (aLower === bLower) {
if (a[0] === aLower && b[0] !== bLower) return -1;
if (a[0] !== aLower && b[0] === bLower) return 1;
return 0;
}
if (aLower < bLower) return -1;
if (aLower > bLower) return 1;
return 0;
}
这里有一个可以用于排序的函数。
它从查找小写字符串之间第一个不常见字符的索引开始。
然后根据优先级分配顺序(-1,0,+1),然后是小写字符串的顺序。
function newSort(a, b) {
let lca = a.toLowerCase();
let lcb = b.toLowerCase();
let len = Math.min(a.length, b.length);
let i = 0;
// find index of first uncommon character
while(lca[i] === lcb[i] && i<len) i++;
// what priority do the types of the uncommon character get
let prioA = !lca[i] ? 0 : /^\d/.test(lca[i]) ? 1 : /^[a-z]/.test(lca[i]) ? 3 : 2;
let prioB = !lcb[i] ? 0 : /^\d/.test(lcb[i]) ? 1 : /^[a-z]/.test(lcb[i]) ? 3 : 2;
let order = prioA > prioB ? 1 : prioA < prioB ? -1
: lca > lcb ? 1 : lca < lcb ? -1 : 0;
return order
}
const stringArray = [
"1!a", "1a!", "!1a", "!a1", "a!1", "a1!"
, "Jane Smith" , "jane doe" , "john doe"
, "abcX", "ABC", "DEFy", "defx"
];
let sortedStringArray = stringArray.sort(newSort);
console.log(sortedStringArray);
我尝试升级 JavaScript 当前的自定义排序功能以创建新的排序顺序
例如(1, 2, 3, 4,..., !@#$%^=+, a, A, b, B, c, C)
function getSortOrder(prop) {
return function (a, b) {
if (isSpecialChar(a[prop], 0) || isSpecialChar(b[prop], 0)) {
return sortData(a[prop], b[prop]);
}
if (isNumeric(a[prop], 0) == "number" || isNumeric(b[prop], 0) == "number") {
return getSortNumeric(a[prop], b[prop]);
}
if (isLetter(a[prop], 0) || isLetter(b[prop], 0)) {
return getSortLetter(a[prop], b[prop]);
}
};
}
function getSortLetter(a, b) {
if ((a.charAt(0) === getLowerCase(a, 0)) && (b.charAt(0) === getUpperCase(b, 0))) {
return sortData(a, b);
}
return sortData(a, b);
}
function getSortNumeric(a, b) {
if (typeof a[prop] == "number") {
return (a[prop] - b[prop]);
} else {
return ((a[prop] < b[prop]) ? -1 : ((a[prop] > b[prop]) ? 1 : 0));
}
}
function sortData(a, b) {
if (a.toLowerCase() < b.toLowerCase()) {
return -1;
} else if (a.toLowerCase() > b.toLowerCase()) {
return 1;
} else {
return 0;
}
}
/**
* Function that is used for the ascending order of number
*
*/
const sortNumberData = (a, b) => a.localeCompare(b, 'en', { numeric: true })
// to check if the data has numeric
function isNumeric(str, index) {
let x = /^[0-9]$/.test(str.charAt(index));
console.log(str, x);
return x;
}
// to determine if the data has neither numeric or letter
function isSpecialChar(str, index) {
return !isNumeric(str, index) && !isLetter(str, index);
}
// to specify the order of letter e.g. (jane doe, Jane Doe, john doe, John doe)
function isLetter(str, index) {
return str.charAt(index).length === 1 && str.match(/[a-z]/i);
}
function getLowerCase(str, index) {
return str.charAt(index).toLowerCase();
}
function getUpperCase(str, index) {
return str.charAt(index).toUpperCase();
}
Json 值的预期结果:
用户列表:
123管理员
321用户
!testAdmin
#adminData
无名氏
简·史密斯
约翰·多伊
李四
Json 值的当前结果:
用户列表:
!testAdmin
#adminData
123管理员
321用户
简·史密斯
无名氏
约翰·多伊
它仍然遵循 Ascii 默认排序顺序。
对于想要的订单,您可以使用 string/object 的蛮力方法。
此方法迭代每对字符串并通过获取顺序检查任何字符,直到找到不同的字符。
const
chars = ' 0123456789!@#$%^=+abcdefghijklmnopqrstuvwxyz',
order = Object.fromEntries(Array.from(chars, ((c, i) => [c, i + 1]))),
sort = (a, b) => {
for (let i = 0, l = Math.min(a.length, b.length); i < l; i++) {
const r = order[a[i].toLowerCase()] - order[b[i].toLowerCase()];
if (r) return r;
}
return a.length - b.length;
},
sortBy = (fn, k) => (a, b) => fn(a[k], b[k]),
data = [{ name: 'abcd' }, { name: 'abc' }, { name: 'John Doe' }, { name: '!testAdmin' }, { name: '#adminData' }, { name: '123Admin' }, { name: '321user' }, { name: 'Jane Smith' }, { name: 'jane doe' }, { name: 'john doe' }];
data.sort(sortBy(sort, 'name'));
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz 建议的方法更简洁,但您的原始代码存在以下问题:
您的 isLetter
函数没有 return 正确的结果。使用下面的 RegExp.test
方法可以解决这个问题:
function isLetter(str, index) {
return str.charAt(index).length === 1 && /^[a-z]/i.test(str);
}
您的 getSortOrder
函数在比较属于不同组(特殊字符/数字/字母)的字符时也无法正确处理排序。要解决这个问题,您可以更改该函数以区分角色何时属于同一组以及何时属于不同组:
function getSortOrder(a, b) {
if (isNumeric(a, 0) && isNumeric(b, 0)) return sortData(a, b);
if (isSpecialChar(a, 0) && isSpecialChar(b, 0)) return sortData(a, b);
if (isLetter(a, 0) && isLetter(b, 0)) return sortData(a, b);
if (isNumeric(a, 0)) return -1;
if (isLetter(a, 0)) return 1;
if (isSpecialChar(a, 0)) {
if (isNumeric(b, 0)) return 1;
return -1;
}
}
最后,sortData
函数不区分大小写。它需要做这样的事情:
function sortData(a, b) {
const aLower = a[0].toLowerCase();
const bLower = b[0].toLowerCase();
if (aLower === bLower) {
if (a[0] === aLower && b[0] !== bLower) return -1;
if (a[0] !== aLower && b[0] === bLower) return 1;
return 0;
}
if (aLower < bLower) return -1;
if (aLower > bLower) return 1;
return 0;
}
这里有一个可以用于排序的函数。
它从查找小写字符串之间第一个不常见字符的索引开始。
然后根据优先级分配顺序(-1,0,+1),然后是小写字符串的顺序。
function newSort(a, b) {
let lca = a.toLowerCase();
let lcb = b.toLowerCase();
let len = Math.min(a.length, b.length);
let i = 0;
// find index of first uncommon character
while(lca[i] === lcb[i] && i<len) i++;
// what priority do the types of the uncommon character get
let prioA = !lca[i] ? 0 : /^\d/.test(lca[i]) ? 1 : /^[a-z]/.test(lca[i]) ? 3 : 2;
let prioB = !lcb[i] ? 0 : /^\d/.test(lcb[i]) ? 1 : /^[a-z]/.test(lcb[i]) ? 3 : 2;
let order = prioA > prioB ? 1 : prioA < prioB ? -1
: lca > lcb ? 1 : lca < lcb ? -1 : 0;
return order
}
const stringArray = [
"1!a", "1a!", "!1a", "!a1", "a!1", "a1!"
, "Jane Smith" , "jane doe" , "john doe"
, "abcX", "ABC", "DEFy", "defx"
];
let sortedStringArray = stringArray.sort(newSort);
console.log(sortedStringArray);