Intenté actualizar la función de clasificación personalizada actual de JavaScript para crear un nuevo orden de clasificación
por ejemplo (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 eg (jane doe, Jane Doe, john doe, John doe) function isLetter(str, index) { return str.charAt(index).length === 1 && str.match(/[az]/i); } function getLowerCase(str, index) { return str.charAt(index).toLowerCase(); } function getUpperCase(str, index) { return str.charAt(index).toUpperCase(); } resultado esperado de los valores Json:
Lista de usuarios:
123Administrador
321usuario
!testAdmin
#adminData
fulano de tal
Jane Smith
john doe
Juan Pérez
Resultados actuales de Json Values:
Lista de usuarios:
!testAdmin
#adminData
123Administrador
321usuario
Jane Smith
fulano de tal
john doe
Todavía sigue el orden de clasificación predeterminado de ASCII.
Podría adoptar un enfoque de fuerza bruta con una cadena/objeto para el orden deseado.
Este enfoque itera cada par de cadenas y verifica cualquier carácter obteniendo el orden hasta encontrar diferentes caracteres.
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; }El enfoque sugerido por Nina Scholz es más conciso, pero esto es lo que estaba mal con su código original:
Su función isLetter no devuelve el resultado correcto. Usar el método RegExp.test como se muestra a continuación solucionaría eso:
function isLetter(str, index) { return str.charAt(index).length === 1 && /^[az]/i.test(str); } Su función getSortOrder tampoco maneja la clasificación correctamente al comparar caracteres que pertenecen a diferentes grupos (carácter especial/número/letra). Para arreglar eso, podrías cambiar esa función para distinguir cuando los personajes están en el mismo grupo versus cuando están en diferentes grupos:
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; } } Finalmente, la función sortData no distingue entre mayúsculas y minúsculas. Tendría que hacer algo como esto:
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; }Aquí hay una función que se puede usar en una ordenación.
Comienza con encontrar el índice del primer carácter poco común entre las cadenas en minúsculas.
Luego asigna el orden (-1,0,+1) dependiendo de una prioridad, y luego el orden de las cadenas en minúsculas.
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 : /^[az]/.test(lca[i]) ? 3 : 2; let prioB = !lcb[i] ? 0 : /^\d/.test(lcb[i]) ? 1 : /^[az]/.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);