在 Javascript 中按降序排序字符串(最有效) ?

W3CSschool 有这样一个例子:

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.sort();
fruits.reverse();

这是在 Javascript 中按降序对字符串排序的最有效方法吗?

更新

答案之一是使用 localeCompare。只是好奇如果我们使用 reverse(),它是否适用于所有地区(也许这是一个单独的问题——请在评论中告诉我) ?

156915 次浏览

Using just sort and reverse a > Z , that is wrong if you want to order lower cases and upper cases strings:

var arr = ["a","b","c","A","B","Z"];


arr.sort().reverse();


console.log(arr)//<-- [ 'c', 'b', 'a', 'Z', 'B', 'A' ] wrong!!!

English characters

var arr = ["a","b","c","A","B","Z"];


arr.sort((a,b)=>b.localeCompare(a))


console.log(arr)

Special characters using locales, in this example es (spanish)

var arr = ["a", "á", "b","c","A","Á","B","Z"];


arr.sort((a, b) => b.localeCompare(a, 'es', {sensitivity: 'base'}))




console.log(arr)

sensitivity in this case is base:

Only strings that differ in base letters compare as unequal. Examples: a ≠ b, a = á, a = A.

If you consider

obj.sort().reverse();

VS

obj.sort((a, b) => (a > b ? -1 : 1))

VS

obj.sort((a, b) => b.localeCompare(a) )

The performance winner is : obj.sort().reverse().

Testing with an array of 10.000 elements, obj.sort().reverse() is faster than obj.sort( function ) (except on chrome), and obj.sort( function ) (using localCompare).

Performance test here :

var results = [[],[],[]]


for(let i = 0; i < 100; i++){
const randomArrayGen = () => Array.from({length: 10000}, () => Math.random().toString(30));
const randomArray = randomArrayGen();
const copyArray = x => x.slice();


obj = copyArray(randomArray);
let t0 = performance.now();
obj.sort().reverse();
let t1 = performance.now();


obj = copyArray(randomArray);
let t2 = performance.now();
obj.sort((a, b) => (a > b ? -1 : 1))
let t3 = performance.now();


obj = copyArray(randomArray);
let t4 = performance.now();
obj.sort((a, b) => b.localeCompare(a))
let t5 = performance.now();


results[0].push(t1 - t0);
results[1].push(t3 - t2);
results[2].push(t5 - t4);
}


const calculateAverage = x => x.reduce((a,b) => a + b) / x.length ;


console.log("obj.sort().reverse():                   " + calculateAverage(results[0]));
console.log("obj.sort((a, b) => (a > b ? -1 : 1)):   " + calculateAverage(results[1]));
console.log("obj.sort((a, b) => b.localeCompare(a)): " + calculateAverage(results[2]));

var arr = ["a","b","c","A","B","Z"];


arr.sort((a,b)=>b.localeCompare(a))


console.log(arr)

I know this is an old question, but an interesting one. This is my solution for a non-special character's input.

var arr = ["a","b","c","A","B","Z"];


console.log(arr.sort((a,b)=> {
const lastCodeIn = b.toLowerCase().charCodeAt();
const lastCode = b.charCodeAt();
const firstCodeIn = a.toLowerCase().charCodeAt();
const firstCode = a.charCodeAt();


if(lastCodeIn - firstCodeIn === 0){
return lastCode - firstCode;
}
return lastCodeIn - firstCodeIn;
})
);//[ 'Z', 'c', 'b', 'B', 'a', 'A' ]

The reason is that ascii code for UPPER case are lower than lower case.

The easiest way to revers the order of sorting is by swapping the operands. In ES2015 that's as easy as [b, a] = [a, b]. A full example:

function compareWithOrder(a, b, shouldReverse = false) {
if (shouldReverse) {
[b, a] = [a, b]
}
return yourComparatorFn(a, b)
}