2010-12-02 6 views
32

J'ai un tableau mixte que je dois trier par ordre alphabétique et par chiffrealpha/tableau numérique Trier mixte

[A1, A10, A11, A12, A2, A3, A4, B10, B2, F1, F12, F3] 

Comment puis-je trier être:

[A1, A2, A3, A4, A10, A11, A12, B2, B10, F1, F3, F12] 

j'ai essayé

arr.sort(function(a,b) {return a - b}); 

mais trie seulement elle par ordre alphabétique. Est-ce que cela peut être fait avec JavaScript ou jQuery?

Merci!

+0

sont les valeurs numériques toujours à la fin de la chaîne? – Orbling

Répondre

53
var reA = /[^a-zA-Z]/g; 
var reN = /[^0-9]/g; 
function sortAlphaNum(a,b) { 
    var aA = a.replace(reA, ""); 
    var bA = b.replace(reA, ""); 
    if(aA === bA) { 
     var aN = parseInt(a.replace(reN, ""), 10); 
     var bN = parseInt(b.replace(reN, ""), 10); 
     return aN === bN ? 0 : aN > bN ? 1 : -1; 
    } else { 
     return aA > bA ? 1 : -1; 
    } 
} 
["A1", "A10", "A11", "A12", "A2", "A3", "A4", "B10", "B2", "F1", "F12", "F3"].sort(sortAlphaNum); 
+0

Juste me battre aussi, seulement une modification que je suggérerais, étant donné la commande des tests, l'expression rationnelle devrait également être ordonnée par l'ajout de '^' et '$' avant 'respectivement sur chacun. – Orbling

+0

Génie! Exactement ce dont j'avais besoin. Je vous remercie!!! – solefald

+0

C'était un homme assez rapide! –

2
var a1 =["A1", "A10", "A11", "A12", "A2", "A3", "A4", "B10", "B2", "F1", "F12", "F3"]; 

var a2 = a1.sort(function(a,b){ 
    var charPart = [a.substring(0,1), b.substring(0,1)], 
     numPart = [a.substring(1)*1, b.substring(1)*1]; 

    if(charPart[0] < charPart[1]) return -1; 
    else if(charPart[0] > charPart[1]) return 1; 
    else{ //(charPart[0] == charPart[1]){ 
     if(numPart[0] < numPart[1]) return -1; 
     else if(numPart[0] > numPart[1]) return 1; 
     return 0; 
    } 
}); 

$('#r').html(a2.toString()) 

http://jsfiddle.net/8fRsD/

2

Cela pourrait le faire:

function parseItem (item) { 
 
    const [, stringPart = '', numberPart = 0] = /(^[a-zA-Z]*)(\d*)$/.exec(item) || []; 
 
    return [stringPart, numberPart]; 
 
} 
 

 
function sort (array) { 
 
    return array.sort((a, b) => { 
 
    const [stringA, numberA] = parseItem(a); 
 
    const [stringB, numberB] = parseItem(b); 
 
    const comparison = stringA.localeCompare(stringB); 
 
    return comparison === 0 ? Number(numberA) - Number(numberB) : comparison; 
 
    }); 
 
} 
 

 
console.log(sort(['A1', 'A10', 'A11', 'A12', 'A2', 'A3', 'A4', 'B10', 'B2', 'F1', 'F12', 'F3']))

6

J'ai eu une situation similaire, mais avait un mélange de caractères alphanumériques & numérique et nécessaire pour trier tout d'abord numérique suivi par alpha numérique, donc:

A10 
1 
5 
A9 
2 
B3 
A2 

nécessaires pour devenir:

1 
2 
5 
A2 
A9 
A10 
B3 

J'ai pu utiliser l'algorithme fourni et pirater un peu plus sur elle pour y parvenir:

var reA = /[^a-zA-Z]/g; 
var reN = /[^0-9]/g; 
function sortAlphaNum(a,b) { 
    var AInt = parseInt(a, 10); 
    var BInt = parseInt(b, 10); 

    if(isNaN(AInt) && isNaN(BInt)){ 
     var aA = a.replace(reA, ""); 
     var bA = b.replace(reA, ""); 
     if(aA === bA) { 
      var aN = parseInt(a.replace(reN, ""), 10); 
      var bN = parseInt(b.replace(reN, ""), 10); 
      return aN === bN ? 0 : aN > bN ? 1 : -1; 
     } else { 
      return aA > bA ? 1 : -1; 
     } 
    }else if(isNaN(AInt)){//A is not an Int 
     return 1;//to make alphanumeric sort first return -1 here 
    }else if(isNaN(BInt)){//B is not an Int 
     return -1;//to make alphanumeric sort first return 1 here 
    }else{ 
     return AInt > BInt ? 1 : -1; 
    } 
} 
var newlist = ["A1", 1, "A10", "A11", "A12", 5, 3, 10, 2, "A2", "A3", "A4", "B10", "B2", "F1", "F12", "F3"].sort(sortAlphaNum); 
+0

'[" a25b "," ab "," a37b "]' produira '[" a25b "," ab "," a37b "]' au lieu de '[" a25b "," a37b "," ab "]' . –

-3
function sortAlphaNum(a, b) { 
    var smlla = a.toLowerCase(); 
    var smllb = b.toLowerCase(); 
    var result = smlla > smllb ? 1 : -1; 
    return result; 
} 
+1

C'est faux. Essayez de comparer 'A10' à' A2'. Cela va trier 'A10' avant' A2', mais 'A2' devrait être trié avant' A10'. – cpburnz

0

J'ai résolu le problème de tri ci-dessus avec le script ci-dessous

arrVals.sort(function(a, b){ 
    //return b.text - a.text; 
    var AInt = parseInt(a.text, 10); 
    var BInt = parseInt(b.text, 10); 

    if ($.isNumeric(a.text) == false && $.isNumeric(b.text) == false) { 
     var aA = a.text 
     var bA = b.text; 
     return aA > bA ? 1 : -1; 
    } else if ($.isNumeric(a.text) == false) { // A is not an Int 
     return 1; // to make alphanumeric sort first return -1 here 
    } else if ($.isNumeric(b.text) == false) { // B is not an Int 
     return -1; // to make alphanumeric sort first return 1 here 
    } else { 
     return AInt < BInt ? 1 : -1; 
    } 
}); 

Cela fonctionne bien pour un tableau bien mélangé. :)

Merci.

1

Ajout à la réponse acceptée d'epascarello, puisque je ne peux pas commenter. Je suis toujours un noob ici. Lorsque l'une des strins n'a pas de numéro, la réponse originale ne fonctionnera pas. Par exemple A et A10 ne seront pas triés dans cet ordre. Par conséquent, vous pourriez essayer de revenir à la normale dans ce cas.

var reA = /[^a-zA-Z]/g; 
var reN = /[^0-9]/g; 
function sortAlphaNum(a,b) { 
    var aA = a.replace(reA, ""); 
    var bA = b.replace(reA, ""); 
    if(aA === bA) { 
     var aN = parseInt(a.replace(reN, ""), 10); 
     var bN = parseInt(b.replace(reN, ""), 10); 
     if(isNaN(bN) || isNaN(bN)){ 
     return a > b ? 1 : -1; 
     } 
     return aN === bN ? 0 : aN > bN ? 1 : -1; 
    } else { 
    return aA > bA ? 1 : -1; 
    } 
} 
["A1", "A10", "A11", "A12", "A2", "A3", "A4", "B10", "B2", "F1", "F12","F3"].sort(sortAlphaNum);` 
2

const sortAlphaNum = (a, b) => a.localeCompare(b, 'en', { numeric: true })

Utilisation:

['A1', 'A10', 'A11', 'A12', 'A2', 'A3', 'A4', 'B10', 'B2', 'F1', 'F12', 'F3'].sort(sortAlphaNum)

donne:

["A1", "A2", "A3", "A4", "A10", "A11", "A12", "B2", "B10", "F1", "F3", "F12"]

Vous pourriez avoir à changer l'argument 'en' à votre locale ou dete rmine par programmation mais cela fonctionne pour les chaînes anglaises.

Aussi localeCompare est pas super toujours soutenu mais si votre transpiling babel qui ne sera pas un problème

0

seul problème avec la solution donnée ci-dessus est que la logique a échoué lorsque les données numériques était même & alphabets varie par exemple 28AB, 28PQR, 28HBC. Voici le code modifié.

var reA = /[^a-zA-Z]/g; 
    var reN = /[^0-9]/g; 
    var AInt = parseInt(a, 10); 
    var BInt = parseInt(b, 10); 
    if(isNaN(AInt) && isNaN(BInt)){ 
     var aA = a.replace(reA, ""); 
     var bA = b.replace(reA, ""); 
     if(aA === bA) { 
      var aN = parseInt(a.replace(reN, ""), 10); 
      var bN = parseInt(b.replace(reN, ""), 10); 
      alert("in if "+aN+" : "+bN); 
      return aN === bN ? 0 : aN > bN ? 1 : -1; 
     } else { 
      return aA > bA ? 1 : -1; 
     } 
    }else if(isNaN(AInt)){//A is not an Int 
     return 1;//to make alphanumeric sort first return 1 here 
    }else if(isNaN(BInt)){//B is not an Int 
     return -1;//to make alphanumeric sort first return -1 here 
    }else if(AInt == BInt) { 
     var aA = a.replace(reA, ""); 
     var bA = b.replace(reA, ""); 
     return aA > bA ? 1 : -1; 
    } 
    else { 
     return AInt > BInt ? 1 : -1; 
    } 
0
alphaNumericCompare(a, b) { 

    let ax = [], bx = []; 

    a.replace(/(\d+)|(\D+)/g, function (_, $1, $2) { ax.push([$1 || Infinity, $2 || '']) }); 
    b.replace(/(\d+)|(\D+)/g, function (_, $1, $2) { bx.push([$1 || Infinity, $2 || '']) }); 

    while (ax.length && bx.length) { 
     let an = ax.shift(); 
     let bn = bx.shift(); 
     let nn = (an[0] - bn[0]) || an[1].localeCompare(bn[1]); 
     if (nn) { 
     return nn; 
     } 
    } 
    return ax.length - bx.length; 
}