2012-01-25 7 views

risposta

265

In (quasi :) una battuta

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

che si traduce in

[ 'bar', 'Foo' ] 

Mentre

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

risultati in

[ 'Foo', 'bar' ] 
+7

Ricorda che le opzioni avanzate di localCompare non sono ancora supportate su tutte le piattaforme/browser. So che non sono usati in questo esempio, ma volevano solo aggiungere per chiarezza. [Vedi MDN per maggiori informazioni] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare) –

+50

Se vuoi coinvolgere localCompare(), potresti basta usare * la sua * capacità di non fare distinzione tra maiuscole e minuscole, ad esempio: 'return a.localeCompare (b, 'en', {'sensitivity': 'base'});' –

+1

+1 per non chiamare 'toLowerCase()' quando 'localeCompare' lo fa già di default in alcuni casi. Puoi leggere ulteriori informazioni sui parametri per passare ad esso qui: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare#Parameters – Milimetric

4

Normalizza il caso nello .sort() con .toLowerCase().

21
arr.sort(function(a,b) { 
    a = a.toLowerCase(); 
    b = b.toLowerCase(); 
    if (a == b) return 0; 
    if (a > b) return 1; 
    return -1; 
}); 
+0

o 'return a === b? 0: a> b? 1: -1; ' –

55
myArray.sort(
    function(a, b) { 
    if (a.toLowerCase() < b.toLowerCase()) return -1; 
    if (a.toLowerCase() > b.toLowerCase()) return 1; 
    return 0; 
    } 
); 

EDIT: prega di notare che ho originariamente scritto questo per illustrare la tecnica piuttosto che la prestazione in mente. Si prega di fare riferimento anche a @Ivan Krechetov per una soluzione più compatta.

+3

Questo può chiamare' toLowerCase' due volte su ogni stringa; sarebbe più efficiente memorizzare le versioni ridotte della stringa nelle variabili. – Jacob

+0

Vero e grazie. L'ho scritto con chiarezza in mente, non con le prestazioni. Credo che dovrei notarlo. –

+1

@Jacob Per essere giusti, la risposta accettata ha lo stesso problema di base: può eventualmente chiamare '.toLowerCase()' più volte per ogni elemento nell'array. Ad esempio, 45 chiamate alla funzione di confronto quando si ordinano 10 elementi in ordine inverso. 'var i = 0; ["z", "y", "x", "w", "v", "u", "t", "s", "r", "q"]. sort (funzione (a, b) {++ i; return a.toLowerCase(). localeCompare (b.toLowerCase());}); console.log ("Chiama per confrontare:" + i); // i === 45' – nothingisnecessary

8

Se si vuole garantire lo stesso ordine indipendentemente dall'ordine degli elementi dell'array di ingresso, ecco un ordinamento 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; 
}); 
3

È inoltre possibile utilizzare l'operatore di 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); 

Gives :

biscuit,Bob,charley,fudge,Fudge 

Il metodo localeCompare è probabilmente bene però ...

Nota: l'operatore Elvis è un "operatore ternario" di breve durata per il caso in cui altrimenti, di solito con incarico.
Se si guarda al:? Lateralmente, sembra che Elvis ...
cioè invece di:

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

è possibile utilizzare:

x = y?1:2; 

cioè quando y è vero, allora return 1 (per assegnazione a x), altrimenti return 2 (per assegnazione a x).

0

Questo può aiutare se avete lottato per capire:

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
arr.sort(function(a,b) { 
    a = a.toLowerCase(); 
    b = b.toLowerCase(); 
    if(a == b) return 0; 
    if(a > b) return 1; 
    return -1; 
}); 

In funzione di cui sopra, se si confronta proprio quando minuscolo due valori a e b, che non avrà il bel risultato.

Esempio: se l'array è [A, a, B, b, c, C, D, d, e, E] e usiamo la funzione sopra riportata, abbiamo esattamente quell'array. Non è cambiato nulla.

Per avere il risultato è [A, a, B, b, C, C, D, D, E, e], dovremmo confronta di nuovo quando due valore minuscole è uguale:

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

Avvolgi le stringhe in / /i. Questo è un modo semplice per usare regex per ignorare l'alloggiamento

1

Le altre risposte presuppongono che l'array contenga stringhe. Il mio metodo è migliore, perché funzionerà anche se l'array contiene null, indefiniti o altri non stringhe.

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

Il null verrà ordinata tra 'nulk' e 'nulm'. Ma lo undefined sarà sempre in ordine ordinato.

+0

' ('' + notdefined) === "undefined" 'così sarebbe stato ordinato prima" z " – MattW

+0

@MattW no, ti stai sbagliando. vedi https://jsfiddle.net/qrw0uy3r/ –

+0

Indovina che avrei dovuto cercare la definizione di 'Array.prototype.sort': | perché la parte about '('' + notdefined) ===" undefined "' * è veramente * true ... il che significa che se si capovolge il -1 e 1 nella funzione sort per invertire l'ordine, i tipi non definiti vengono ancora ordinati al fine. Deve anche essere considerato quando si usa la funzione di confronto al di fuori del contesto di un ordinamento di array (come lo sono stato quando mi sono imbattuto in questa domanda). – MattW

3

È anche possibile utilizzare il nuovo Intl.Collator().compare, per MDN è more efficient quando si ordinano gli array. Lo svantaggio è che dal momento che non è supportato dai browser più vecchi. MDN afferma che non è supportato affatto in Safari. È necessario verificarlo, poiché indica che è supportato Intl.Collator.

When comparing large numbers of strings, such as in sorting large arrays, it is better to create an Intl.Collator object and use the function provided by its compare property

["Foo", "bar"].sort(Intl.Collator().compare); //["bar", "Foo"] 
+0

Vecchi browser vecchi; Sto usando questo. –

0

ho avvolto la risposta superiore in una polyfill quindi posso chiamare .sortIgnoreCase() su matrici di stringhe

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

È tempo di rivisitare questa vecchia domanda.

Non utilizzare soluzioni basate su toLowerCase. Sono inefficienti e semplicemente non funzionano in alcune lingue (turco per esempio). Preferisco questo:

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

Controllare il documentation per la compatibilità del browser e tutto quello che c'è da sapere su l'opzione sensitivity.

Problemi correlati