2010-12-02 28 views
32

que tiene una matriz mixta que necesito para ordenar por orden alfabético y luego por dígitosalfa Ordenar mixta/matriz numérica

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

¿Cómo puedo ordenar que fuera:

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

he intentado

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

pero eso solo lo ordena alfabéticamente. ¿Se puede hacer esto con JavaScript directo o jQuery?

¡Gracias!

+0

son los valores numéricos siempre al final de la cadena? – Orbling

Respuesta

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

Solo páseme también, solo sugeriría una modificación, dado el orden de las pruebas, la expresión regular también debería ordenarse mediante la adición de '^' y '$' adelante y atrás respectivamente en cada una. – Orbling

+0

Genius! Exactamente lo que necesitaba ¡¡¡Gracias!!! – solefald

+0

¡Era un hombre bastante rápido! –

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

Esto podría hacerlo:

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

tuve una situación similar, pero, tenía una mezcla de caracteres alfanuméricos & numérico y necesaria ordenar todo primero numérico seguido de alfa numérica, por lo que:

A10 
1 
5 
A9 
2 
B3 
A2 

necesaria para convertirse en:

1 
2 
5 
A2 
A9 
A10 
B3 

pude usar el algoritmo suministrado y cortar un poco más sobre ella para lograr esto:

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 "]' producirá '[" a25b "," ab "," a37b "]' en lugar 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

Esto está mal. Intente comparar 'A10' con' A2'. Esto ordenará 'A10' antes de' A2', pero 'A2' debería clasificarse antes de' A10'. – cpburnz

0

He resuelto el problema de clasificación anterior con la siguiente secuencia de comandos

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; 
    } 
}); 

Esto funciona bien para una matriz bien mezclado. :)

Gracias.

1

Agregando a la respuesta aceptada de epascarello, ya que no puedo comentar sobre ello. Todavía soy un novato aquí. Cuando uno de los strinngs no tiene un número, la respuesta original no funcionará. Por ejemplo, A y A10 no se ordenarán en ese orden. Por lo tanto, es posible que desee volver al tipo normal en ese caso.

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 })

Uso:

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

da:

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

puede que tenga que cambiar el argumento 'en' a su localidad o dete rmine programáticamente pero esto funciona para cadenas en inglés.

También localeCompare no se admite súper consistentemente pero si su transpiling con Babel que no será un problema

0

El único problema con la solución dada anteriormente era que la lógica no cuando los datos numéricos era mismas & alfabetos variaron por ejemplo 28AB, 28PQR, 28HBC. Aquí está el código modificado.

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; 
}