我有一个字符串数组,需要在JavaScript中排序,但不区分大小写。如何执行呢?
我有一个字符串数组,需要在JavaScript中排序,但不区分大小写。如何执行呢?
Answers:
在(几乎:)单线
["Foo", "bar"].sort(function (a, b) {
return a.toLowerCase().localeCompare(b.toLowerCase());
});
导致
[ 'bar', 'Foo' ]
而
["Foo", "bar"].sort();
结果是
[ 'Foo', 'bar' ]
return a.localeCompare(b, 'en', {'sensitivity': 'base'});
toLowerCase()
的时候localeCompare
已经这样做,默认情况下在某些情况下。:你可以阅读更多有关参数传递给在这里developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
myArray.sort(
function(a, b) {
if (a.toLowerCase() < b.toLowerCase()) return -1;
if (a.toLowerCase() > b.toLowerCase()) return 1;
return 0;
}
);
编辑: 请注意,我最初是为了说明该技术而写的,而不是考虑性能。另请参阅答案@Ivan Krechetov,以获取更紧凑的解决方案。
toLowerCase
每个字符串可以调用两次;将字符串的降低版本存储在变量中会更有效。
.toLowerCase()
为数组中的每个项目多次调用。例如,当以相反顺序对10个项目进行排序时,有45个调用compare函数。var i = 0; ["z","y","x","w","v","u","t","s","r","q"].sort(function (a, b) {++i; return a.toLowerCase().localeCompare(b.toLowerCase());}); console.log("Calls to Compare: " + i); // i === 45
现在该重新讨论这个老问题了。
您不应该使用依赖的解决方案toLowerCase
。它们效率低下,根本无法在某些语言中使用(例如土耳其语)。喜欢这个:
['Foo', 'bar'].sort((a, b) => a.localeCompare(b, undefined, {sensitivity: 'base'}))
查看文档以了解浏览器兼容性,以及有关该sensitivity
选项的所有信息。
arr.sort(function(a,b) {
a = a.toLowerCase();
b = b.toLowerCase();
if (a == b) return 0;
if (a > b) return 1;
return -1;
});
return a === b ? 0 : a > b ? 1 : -1;
["111", "33"]
,我们可能希望它返回,["111", "33"]
因为在字符代码排序中1在3之前。但是,此答案中的函数将返回,["33", "111"]
因为number 33
小于number 111
。
"33" > "111" === true
和33 > 111 === false
。它按预期工作。
您还可以使用Intl.Collator().compare
每个MDN 的new ,对数组进行排序时效率更高。缺点是旧版浏览器不支持它。MDN指出Safari完全不支持它。需要验证它,因为它表明Intl.Collator
受支持。
比较大量字符串时,例如在对大型数组进行排序时,最好创建一个Intl.Collator对象并使用其compare属性提供的功能。
["Foo", "bar"].sort(Intl.Collator().compare); //["bar", "Foo"]
如果您想保证相同的顺序而不管输入数组中元素的顺序如何,这里是一种稳定的排序:
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;
});
规范化的情况下.sort()
用.toLowerCase()
。
您还可以使用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);
给出:
biscuit,Bob,charley,fudge,Fudge
虽然localeCompare方法可能还不错...
注意:Elvis运算符是“三元运算符”的简写形式,否则,通常带有赋值。
如果您将?:放在侧面看,看起来就像猫王...,
而不是:
if (y) {
x = 1;
} else {
x = 2;
}
您可以使用:
x = y?1:2;
即,当y为true时,则返回1(分配给x),否则返回2(分配给x)。
x = y ? y : z
,您可以这样做x = y ?: z
。Javascript没有实际的Elvis运算符,但是您可以x = y || z
以类似的方式使用。
其他答案假定该数组包含字符串。我的方法更好,因为即使数组包含null,undefined或其他非字符串也可以使用。
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;
}
该null
将“nulk”和“nulm”之间进行排序。但undefined
将始终排在最后。
(''+notdefined) === "undefined"
所以它在“ z”之前排序
Array.prototype.sort
:| 的定义 因为有关的部分(''+notdefined) === "undefined"
确实是正确的……这意味着,如果在sort函数中翻转-1和1以颠倒顺序,则undefined仍会排序到最后。当在数组排序的上下文之外使用比较函数时,也需要考虑它(就像我遇到这个问题时一样)。
Array.prototype.sort
定义-再加上一些评论。首先,不需要(''+a)
-将ECMAScript要求toString()
在将元素传递到compareFn之前对其进行调用。其次,在比较相等(包括大小写相等)字符串时ignoreCase
返回的事实1
意味着,如果有重复的值,则规范不会定义结果(我认为,只要发生一些不必要的交换,就可以了)。
undefined
是一个特例,对于任何x x <undefined和x> undefined都是false。那undefined
永远是最后,是sort的sort实现的副产品。我试图将(''+ a)更改为简单的a,但是失败了。我明白了TypeError: a.toUpperCase is not a function
。显然toString
是不能在调用compareFn调用。
undefined
compareFn 从未被称为
ES6版本:
["Foo", "bar"].sort((a, b) => a.localeCompare(b, 'en', { sensitivity: 'base' }))
来源:https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare
为了支持已接受的答案,我想补充一点,下面的函数似乎改变了要排序的原始数组中的值,这样不仅可以对小写字母进行排序,还可以将大写字母的值更改为小写字母。这对我来说是个问题,因为即使我希望看到Mary旁边的Mary,但我也不希望将Mary的第一个值的大小写更改为小写。
myArray.sort(
function(a, b) {
if (a.toLowerCase() < b.toLowerCase()) return -1;
if (a.toLowerCase() > b.toLowerCase()) return 1;
return 0;
}
);
在我的实验中,来自已接受答案的以下函数可以正确排序,但不会更改值。
["Foo", "bar"].sort(function (a, b) {
return a.toLowerCase().localeCompare(b.toLowerCase());
});
如果您难以理解,这可能会有所帮助:
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.
***/
arr.sort(function(a,b) {
a = a.toLowerCase();
b = b.toLowerCase();
if( a == b) return 0;
if( a > b) return 1;
return -1;
});
在上面的函数中,如果仅比较小写的两个值a和b,我们将不会得到漂亮的结果。
例如,如果数组是[A,a,B,b,c,C,D,d,e,E]并且我们使用上面的函数,那么我们就是那个数组。它什么都没改变。
要得到的结果是[A,a,B,b,C,c,D,d,E,e],当两个小写值相等时,我们应该再次比较:
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;
}
}
}
我将顶部答案包装在polyfill中,以便可以在字符串数组上调用.sortIgnoreCase()
// Array.sortIgnoreCase() polyfill
if (!Array.prototype.sortIgnoreCase) {
Array.prototype.sortIgnoreCase = function () {
return this.sort(function (a, b) {
return a.toLowerCase().localeCompare(b.toLowerCase());
});
};
}