web-dev-qa-db-fra.com

Comment effectuer un tri en JavaScript sans tenir compte de la casse

J'ai un tableau de chaînes que je dois trier en JavaScript, mais sans distinction de casse Comment effectuer cela?

169
Jérôme Verstrynge

Dans (presque :) un one-liner 

["Foo", "bar"].sort(function (a, b) {
    return a.toLowerCase().localeCompare(b.toLowerCase());
});

Ce qui résulte en

[ 'bar', 'Foo' ]

Tandis que

["Foo", "bar"].sort();

résulte en

[ 'Foo', 'bar' ]
326
Ivan Krechetov
myArray.sort(
  function(a, b) {
    if (a.toLowerCase() < b.toLowerCase()) return -1;
    if (a.toLowerCase() > b.toLowerCase()) return 1;
    return 0;
  }
);

EDIT: .__ Veuillez noter que j’ai initialement écrit ceci pour illustrer la technique plutôt que de penser à la performance. Veuillez également vous référer à la réponse @Ivan Krechetov pour une solution plus compacte.

58
ron tornambe
arr.sort(function(a,b) {
    a = a.toLowerCase();
    b = b.toLowerCase();
    if (a == b) return 0;
    if (a > b) return 1;
    return -1;
});
24
Niet the Dark Absol

Il est temps de revenir sur cette vieille question.

Vous ne devez pas utiliser de solutions reposant sur toLowerCase. Ils sont inefficient et simplement ne fonctionnent pas dans certaines langues (le turc par exemple). Préfère ceci:

['Foo', 'bar'].sort((a, b) => a.localeCompare(b, undefined, {sensitivity: 'base'}))

Vérifiez la documentation pour la compatibilité du navigateur et tout ce qu'il y a à savoir sur l'option sensitivity.

22
ZunTzu

Si vous voulez garantir le même ordre indépendamment de l'ordre des éléments dans le tableau en entrée, voici un tri stable :

myArray.sort(function(a, b) {
    /* Storing case insensitive comparison */
    var comparison = a.toLowerCase().localeCompare(b.toLowerCase());
    /* If strings are equal in case insensitive comparison */
    if (comparison === 0) {
        /* Return case sensitive comparison instead */
        return a.localeCompare(b);
    }
    /* Otherwise return result */
    return comparison;
});
10
Aalex Gabi

Vous pouvez également utiliser le nouveau Intl.Collator().compare , par MDN, c'est plus efficace lors du tri des tableaux. L'inconvénient est qu'il n'est pas supporté par les anciens navigateurs. MDN indique qu'il n'est pas du tout pris en charge dans Safari. Besoin de le vérifier, car il est indiqué que Intl.Collator est pris en charge. 

Lors de la comparaison d'un grand nombre de chaînes, comme lors du tri 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

["Foo", "bar"].sort(Intl.Collator().compare); //["bar", "Foo"]
7
mateuscb

Normalisez le cas dans .sort() avec .toLowerCase().

4
user1106925

Les autres réponses supposent que le tableau contient des chaînes. Ma méthode est meilleure, car elle fonctionnera même si le tableau contient null, undefined ou d'autres non-chaînes.

var notdefined;
var myarray = ['a', 'c', null, notdefined, 'nulk', 'BYE', 'nulm'];

myarray.sort(ignoreCase);

alert(JSON.stringify(myarray));    // show the result

function ignoreCase(a,b) {
    return (''+a).toUpperCase() < (''+b).toUpperCase() ? -1 : 1;
}

La null sera triée entre 'nulk' et 'nulm'. Mais la undefined sera toujours trié en dernier.

3
John Henckel

Vous pouvez également utiliser l'opérateur Elvis:

arr = ['Bob', 'charley', 'fudge', 'Fudge', 'biscuit'];
arr.sort(function(s1, s2){
    var l=s1.toLowerCase(), m=s2.toLowerCase();
    return l===m?0:l>m?1:-1;
});
console.log(arr);

Donne:

biscuit,Bob,charley,fudge,Fudge

La méthode localeCompare est probablement bien si ...

Remarque: L'opérateur Elvis est un "opérateur ternaire" abrégé, si if else, généralement avec affectation.
Si vous regardez le?: De côté, cela ressemble à Elvis ...
c'est à dire. au lieu de:

if (y) {
  x = 1;
} else {
  x = 2;
}

vous pouvez utiliser:

x = y?1:2;

c.-à-d. lorsque y est vrai, retourne 1 (pour l'affectation à x), sinon retourne 2 (pour l'affectation à x).

3
AndyS

Cela peut aider si vous avez du mal à comprendre:

var array = ["sort", "Me", "alphabetically", "But", "Ignore", "case"];
console.log('Unordered array ---', array, '------------');

array.sort(function(a,b) {
    a = a.toLowerCase();
    b = b.toLowerCase();
    console.log("Compare '" + a + "' and '" + b + "'");

    if( a == b) {
        console.log('Comparison result, 0 --- leave as is ');
        return 0;
    }
    if( a > b) {
        console.log('Comparison result, 1 --- move '+b+' to before '+a+' ');
        return 1;
    }
    console.log('Comparison result, -1 --- move '+a+' to before '+b+' ');
    return -1;


});

console.log('Ordered array ---', array, '------------');


// return logic

/***
If compareFunction(a, b) is less than 0, sort a to a lower index than b, i.e. a comes first.
If compareFunction(a, b) returns 0, leave a and b unchanged with respect to each other, but sorted with respect to all different elements. Note: the ECMAscript standard does not guarantee this behaviour, and thus not all browsers (e.g. Mozilla versions dating back to at least 2003) respect this.
If compareFunction(a, b) is greater than 0, sort b to a lower index than a.
***/

http://jsfiddle.net/ianjamieson/wmxn2ram/1/

0
Ian Jamieson

J'ai enveloppé la première réponse dans un polyfill afin que je puisse appeler .sortIgnoreCase () sur des tableaux de chaînes

// Array.sortIgnoreCase() polyfill
if (!Array.prototype.sortIgnoreCase) {
    Array.prototype.sortIgnoreCase = function () {
        return this.sort(function (a, b) {
            return a.toLowerCase().localeCompare(b.toLowerCase());
        });
    };
}
0
Jason
arr.sort(function(a,b) {
    a = a.toLowerCase();
    b = b.toLowerCase();
    if( a == b) return 0;
    if( a > b) return 1;
    return -1;
});

Dans la fonction ci-dessus, si nous comparons simplement lorsque les minuscules deux valeurs a et b, nous n'aurons pas le joli résultat.

Exemple, si le tableau est [A, a, B, b, c, C, D, d, e, E] et que nous utilisons la fonction ci-dessus, nous avons exactement ce tableau. Cela n'a rien changé.

Pour que le résultat soit [A, a, B, b, C, D, d, E, e], comparons à nouveau lorsque deux valeurs minuscules sont égales:

function caseInsensitiveComparator(valueA, valueB) {
    var valueALowerCase = valueA.toLowerCase();
    var valueBLowerCase = valueB.toLowerCase();

    if (valueALowerCase < valueBLowerCase) {
        return -1;
    } else if (valueALowerCase > valueBLowerCase) {
        return 1;
    } else { //valueALowerCase === valueBLowerCase
        if (valueA < valueB) {
            return -1;
        } else if (valueA > valueB) {
            return 1;
        } else {
            return 0;
        }
    }
}
0
Envy