Pytanie Sortuj mieszaną tablicę alfanumeryczną


Mam mieszaną tablicę, którą muszę sortować alfabetycznie, a następnie według cyfr

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

jak to posortować?

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

próbowałem

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

ale to tylko sortuje alfabetycznie. Czy można to zrobić za pomocą prostego JavaScriptu lub jQuery?

Dziękuję Ci!


35
2017-12-02 21:38


pochodzenie


Czy wartości liczbowe są zawsze na końcu ciągu? - Orbling


Odpowiedzi:


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

62
2017-12-02 21:52



Po prostu mnie pobiję, tylko sugeruję modyfikację, biorąc pod uwagę kolejność testów, regexp powinno być również uporządkowane poprzez dodanie ^ i $ z przodu iz tyłu odpowiednio na każdym z nich. - Orbling
Geniusz! Dokładnie to, czego potrzebowałem. Dziękuję Ci!!! - solefald
Więc nadrabiam trochę spóźnienia ... ale nie potrzebujesz tego else blok od pierwszego if będzie return gdyby aA === bA - phatskat
@Noitidart preferencji. Nie powinno być żadnej różnicy między tymi dwoma. - epascarello
To dobra odpowiedź, ale bardzo potrzebuje komentarzy. Zajęło mi trochę czasu, aby przeczytać to i ma to sens. - zfrisch


Miałem podobną sytuację, ale posiadałem kombinację alfanumeryczną i numeryczną. Najpierw sortowałem wszystkie cyfry, a następnie alfanumerycznie:

A10
1
5
A9
2
B3
A2

musi stać się:

1
2
5
A2
A9
A10
B3

Udało mi się użyć dostarczonego algorytmu i zhakować trochę więcej, aby to osiągnąć:

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

7
2017-07-14 17:58



["a25b", "ab", "a37b"] wytworzy [ "a25b", "ab", "a37b" ] zamiast [ "a25b", "a37b", "ab" ]. - 林果皞


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

Stosowanie:

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

Daje:

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

Być może będziesz musiał zmienić 'en' argument do twojego ustawienia narodowego lub określ programowo, ale działa to w przypadku ciągów angielskich.

Również localeCompare nie jest super konsekwentnie wspierany, ale jeśli twoja transpozycja z babelem nie będzie problemem


6
2018-05-26 08:45





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
2017-12-02 21:56





To może zrobić:

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']))


2
2017-12-02 22:02





Dodanie do zaakceptowanej odpowiedzi z epascarello, ponieważ nie mogę tego komentować. Wciąż jestem tu noobem. Gdy jeden z numerów nie ma numeru, oryginalna odpowiedź nie zadziała. Na przykład A i A10 nie zostaną posortowane w tej kolejności. Stąd możesz nie powrócić do normalnego sortowania w tym przypadku.

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

1
2017-10-24 18:33





Jedynym problemem z powyższym rozwiązaniem było to, że logika nie powiodła się, gdy dane numeryczne były takie same i zmieniono alfabety np. 28AB, 28PQR, 28HBC. Oto zmodyfikowany kod.

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

1
2018-06-02 11:45



najlepszą odpowiedzią na wszystkie rodzaje mieszanych wartości - wielkie dzięki! :) - meistermuh


Rozwiązałem powyższy problem z sortowaniem za pomocą poniższego skryptu

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

Działa to dobrze dla dobrze wymieszanej tablicy. :)

Dziękuję Ci.


0
2017-07-12 09:38





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

0
2018-02-07 05:00





Oto aktualizacja maszynowa ES6 do tej odpowiedzi.

export function SortAlphaNum(a: string, b: string) {
const reA = /[^a-zA-Z]/g;
const reN = /[^0-9]/g;
const aA = a.replace(reA, "");
const bA = b.replace(reA, "");
if (aA === bA) {
    const aN = parseInt(a.replace(reN, ""), 10);
    const bN = parseInt(b.replace(reN, ""), 10);
    return aN === bN ? 0 : aN > bN ? 1 : -1;
} else {
    return aA > bA ? 1 : -1;
}

}


0
2017-08-14 20:04





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

-3
2017-07-14 00:27



To jest źle. Spróbuj porównać A10 do A2. To się posortuje A10 przed A2, ale A2 należy wcześniej posortować A10. - cpburnz