une - type de variable javascript




Javascript: sorte naturelle de chaînes alphanumériques (4)

Je suis à la recherche de la façon la plus simple de trier un tableau constitué de chiffres et de texte, et une combinaison de ceux-ci.

Par exemple

'123asd'
'19asd'
'12345asd'
'asd123'
'asd12'

se transforme en

'19asd'
'123asd'
'12345asd'
'asd12'
'asd123'

Cela va être utilisé en combinaison avec la solution à une autre question que j'ai posée ici .

La fonction de tri fonctionne en soi, ce dont j'ai besoin est une fonction qui peut dire que '19asd' est plus petit que '123asd'.

J'écris ceci en JavaScript.

Edit: comme l' a souligné adormitu , ce que je recherche est une fonction de tri naturel


Ceci est maintenant possible dans les navigateurs modernes en utilisant localeCompare. En passant l'option numeric: true , il reconnaîtra intelligemment les nombres. Vous pouvez faire une distinction entre la casse et la sensitivity: 'base' . Testé dans Chrome, Firefox et IE11.

Voici un exemple. Il renvoie 1 , ce qui signifie 10 va après 2:

'10'.localeCompare('2', undefined, {numeric: true, sensitivity: 'base'})

Pour les performances lors du tri d'un grand nombre de chaînes, l'article dit:

Lorsque vous comparez un grand nombre de chaînes, par exemple pour trier de grands tableaux, il est préférable de créer un objet Intl.Collator et d'utiliser la fonction fournie par sa propriété compare. Lien Docs

var collator = new Intl.Collator(undefined, {numeric: true, sensitivity: 'base'});
var myArray = ['1_Document', '11_Document', '2_Document'];
console.log(myArray.sort(collator.compare));



Imaginez une fonction de remplissage à 8 chiffres qui transforme:

  • '123asd' -> '00000123asd'
  • '19asd' -> '00000019asd'

Nous pouvons utiliser les chaînes rembourrées pour nous aider à trier '19asd' avant '123asd'.

Utilisez l'expression régulière /\d+/g pour trouver tous les nombres qui doivent être complétés:

str.replace(/\d+/g, pad)

Ce qui suit démontre le tri en utilisant cette technique:

var list = [
    '123asd',
    '19asd',
    '12345asd',
    'asd123',
    'asd12'
];

function pad(n) { return ("00000000" + n).substr(-8); }
function natural_expand(a) { return a.replace(/\d+/g, pad) };
function natural_compare(a, b) {
    return natural_expand(a).localeCompare(natural_expand(b));
}

console.log(list.map(natural_expand).sort()); // intermediate values
console.log(list.sort(natural_compare)); // result

Les résultats intermédiaires montrent ce que fait la routine natural_expand () et vous permettent de comprendre comment fonctionnera la routine naturelle_compare suivante:

[
  "00000019asd",
  "00000123asd",
  "00012345asd",
  "asd00000012",
  "asd00000123"
]

Les sorties:

[
  "19asd",
  "123asd",
  "12345asd",
  "asd12",
  "asd123"
]

Pour comparer les valeurs, vous pouvez utiliser une méthode de comparaison

function naturalSorter(as, bs){
    var a, b, a1, b1, i= 0, n, L,
    rx=/(\.\d+)|(\d+(\.\d+)?)|([^\d.]+)|(\.\D+)|(\.$)/g;
    if(as=== bs) return 0;
    a= as.toLowerCase().match(rx);
    b= bs.toLowerCase().match(rx);
    L= a.length;
    while(i<L){
        if(!b[i]) return 1;
        a1= a[i],
        b1= b[i++];
        if(a1!== b1){
            n= a1-b1;
            if(!isNaN(n)) return n;
            return a1>b1? 1:-1;
        }
    }
    return b[i]? -1:0;
}

Mais pour accélérer le tri d'un tableau, fixez le tableau avant le tri, vous n'avez donc qu'à faire des conversions en minuscules et l'expression régulière une fois au lieu de chaque étape du tri.

function naturalSort(ar, index){
    var L= ar.length, i, who, next, 
    isi= typeof index== 'number', 
    rx=  /(\.\d+)|(\d+(\.\d+)?)|([^\d.]+)|(\.(\D+|$))/g;
    function nSort(aa, bb){
        var a= aa[0], b= bb[0], a1, b1, i= 0, n, L= a.length;
        while(i<L){
            if(!b[i]) return 1;
            a1= a[i];
            b1= b[i++];
            if(a1!== b1){
                n= a1-b1;
                if(!isNaN(n)) return n;
                return a1>b1? 1: -1;
            }
        }
        return b[i]!= undefined? -1: 0;
    }
    for(i= 0; i<L; i++){
        who= ar[i];
        next= isi? ar[i][index] || '': who;
        ar[i]= [String(next).toLowerCase().match(rx), who];
    }
    ar.sort(nSort);
    for(i= 0; i<L; i++){
        ar[i]= ar[i][1];
    }
}






natural-sort