我需要找到所有值都相等的数组。最快的方法是什么?我应该遍历它并只是比较值吗?
['a', 'a', 'a', 'a'] // true
['a', 'a', 'b', 'a'] // false
a.join(',').split(a[0]).length === a.length + 1
我需要找到所有值都相等的数组。最快的方法是什么?我应该遍历它并只是比较值吗?
['a', 'a', 'a', 'a'] // true
['a', 'a', 'b', 'a'] // false
a.join(',').split(a[0]).length === a.length + 1
Answers:
const allEqual = arr => arr.every( v => v === arr[0] )
allEqual( [1,1,1,1] ) // true
或单线:
[1,1,1,1].every( (val, i, arr) => val === arr[0] ) // true
Array.prototype.every(来自MDN):该every()
方法测试数组中的所有元素是否通过提供的功能实现的测试。
const everythings_equal = array => array.every(thing => thing === array[0]);
some
代替every
: arr.some( v => v !== arr[0] )
。这将在第一个元素不等于时返回arr[0]
。
every
也早早返回。
编辑:是红色忍者:
!!array.reduce(function(a, b){ return (a === b) ? a : NaN; });
结果:
var array = ["a", "a", "a"] => result: "true"
var array = ["a", "b", "a"] => result: "false"
var array = ["false", ""] => result: "false"
var array = ["false", false] => result: "false"
var array = ["false", "false"] => result: "true"
var array = [NaN, NaN] => result: "false"
警告:
var array = [] => result: TypeError thrown
这是因为我们没有传递initialValue。因此,您不妨先检查一下array.length
。
false
s 组成,我认为这是行不通的!例如try [false,false,false] .reduce(function(a,b){return(a === b)?a:false;});
["false", ""]
返回true
:/
NaN
。由于NaN === NaN
和NaN !== NaN
均为假,因此可以保证一旦将prev
设置为NaN,则没有值可以将其取出。此外,添加双重否定会将结果转换为true
和false
,因为这NaN
是虚假的。最终形式:!!array.reduce(function(a, b){ return (a === b) ? a : NaN; });
这可行。您通过使用原型在Array上创建一个方法。
if (Array.prototype.allValuesSame === undefined) {
Array.prototype.allValuesSame = function() {
for (let i = 1; i < this.length; i++) {
if (this[i] !== this[0]) {
return false;
}
}
return true;
}
}
以此方式调用:
let a = ['a', 'a', 'a'];
let b = a.allValuesSame(); // true
a = ['a', 'b', 'a'];
b = a.allValuesSame(); // false
Array.prototype
恰好(甚至是IE6)。某些早期版本的IE不支持扩充功能,这只是DOM元素原型。
allValuesSame
循环
在JavaScript 1.6中,您可以使用Array.every
:
function AllTheSame(array) {
var first = array[0];
return array.every(function(element) {
return element === first;
});
}
您可能需要进行完整性检查,例如,当数组中没有元素时。(另外,这是不行的,当所有的元素都是NaN
因为NaN !== NaN
,但这不应该是一个问题,对吧?)
您可以将数组变成集合。如果Set的大小等于1,则Array的所有元素均相等。
function allEqual(arr) {
return new Set(arr).size == 1;
}
allEqual(['a', 'a', 'a', 'a']); // true
allEqual(['a', 'a', 'b', 'a']); // false
allEqual([NaN, NaN])
给出true
。
为了进行性能比较,我还做了一个基准测试:
function allAreEqual(array){
if(!array.length) return true;
// I also made sure it works with [false, false] array
return array.reduce(function(a, b){return (a === b)?a:(!b);}) === array[0];
}
function same(a) {
if (!a.length) return true;
return !a.filter(function (e) {
return e !== a[0];
}).length;
}
function allTheSame(array) {
var first = array[0];
return array.every(function(element) {
return element === first;
});
}
function useSome(array){
return !array.some(function(value, index, array){
return value !== array[0];
});
}
结果:
allAreEqual x 47,565 ops/sec ±0.16% (100 runs sampled)
same x 42,529 ops/sec ±1.74% (92 runs sampled)
allTheSame x 66,437 ops/sec ±0.45% (102 runs sampled)
useSome x 70,102 ops/sec ±0.27% (100 runs sampled)
因此,显然使用内置array.some()是采样方法中最快的方法。
Array#some
有时会表现不佳,是因为一旦回调函数返回true,它就会停止迭代。因此,如果所有元素实际上都相等,则性能应与相同Array#every
。当所有元素都不相等时的相对性能将根据第一个不匹配元素的索引而变化。
使用下划线/破折号的最短答案
function elementsEqual(arr) {
return !_.without(arr, arr[0]).length
}
规格:
elementsEqual(null) // throws error
elementsEqual([]) // true
elementsEqual({}) // true
elementsEqual([1]) // true
elementsEqual([1,2]) // false
elementsEqual(NaN) // true
编辑:
甚至更短,受汤姆的回答启发:
function elementsEqual2(arr) {
return _.uniq(arr).length <= 1;
}
规格:
elementsEqual2(null) // true (beware, it's different than above)
elementsEqual2([]) // true
elementsEqual2({}) // true
elementsEqual2([1]) // true
elementsEqual2([1,2]) // false
elementsEqual2(NaN) // true
如果您已经在使用underscore.js,那么这里是另一个使用方法_.uniq
:
function allEqual(arr) {
return _.uniq(arr).length === 1;
}
_.uniq
返回数组的无重复版本。如果所有值都相同,则长度将为1。
如评论中所述,鉴于您可能期望返回一个空数组true
,那么您还应该检查这种情况:
function allEqual(arr) {
return arr.length === 0 || _.uniq(arr).length === 1;
}
false
。虽然我认为应该如此true
。更改为.length <= 1
就足够了。
是的,您还可以使用以下过滤器对其进行检查,非常简单,检查每个值是否与第一个相同:
//ES6
function sameValues(arr) {
return arr.filter((v,i,a)=>v===a[0]).length === arr.length;
}
也可以使用数组上的每种方法来完成:
//ES6
function sameValues(arr) {
return arr.every((v,i,a)=>v===a[0]);
}
您可以如下检查数组:
sameValues(['a', 'a', 'a', 'a']); // true
sameValues(['a', 'a', 'b', 'a']); // false
或者,如果您经常重复使用它,则可以将其添加到JavaScript中的本机Array功能中:
//ES6
Array.prototype.sameValues = Array.prototype.sameValues || function(){
this.every((v,i,a)=>v===a[0]);
}
您可以如下检查数组:
['a', 'a', 'a', 'a'].sameValues(); // true
['a', 'a', 'b', 'a'].sameValues(); // false
Array.every
如果支持,可以使用:
var equals = array.every(function(value, index, array){
return value === array[0];
});
循环的替代方法可能类似于 sort
var temp = array.slice(0).sort();
var equals = temp[0] === temp[temp.length - 1];
或者,如果这些项目像问题一样,则有些肮脏,例如:
var equals = array.join('').split(array[0]).join('').length === 0;
也可以。
equals = !array.some( (v,i,a) => v!==a[0] )
。否则,您只是在检查是否有任何值等于第一个值,当然,该值总是正确的:)
some
不是every
我在第一段中提到的。:)感谢您的收获!
您可以使用Array.prototype.every,Object.is和ES6箭头功能来获得以下内容:
const all = arr => arr.every(x => Object.is(arr[0], x));
更新新解决方案:检查索引
let a = ['a', 'a', 'b', 'a'];
let a = ['a', 'a', 'a', 'a'];
let check = (list) => list.every(item => list.indexOf(item) === 0);
check(a); // false;
check(b); // true;
ES6更新:使用list.every
是最快的方法:
let a = ['a', 'a', 'b', 'a'];
let check = (list) => list.every(item => item === list[0]);
旧版:
var listTrue = ['a', 'a', 'a', 'a'];
var listFalse = ['a', 'a', 'a', 'ab'];
function areWeTheSame(list) {
var sample = list[0];
return (list.every((item) => item === sample));
}
您可以使用此:
function same(a) {
if (!a.length) return true;
return !a.filter(function (e) {
return e !== a[0];
}).length;
}
该函数首先检查数组是否为空。如果是,则它们的值是相等的。否则,它将对数组进行过滤,并接受与第一个元素不同的所有元素。如果没有这样的值=>数组仅包含相等的元素,否则不包含。
Underscore的_.isEqual(object, other)
功能似乎适用于数组。数组中项目的顺序在检查是否相等时很重要。参见http://underscorejs.org/#isEqual。
var listTrue = ['a', 'a', 'a', 'a'];
var listFalse = ['a', 'a', 'a', 'ab'];
function areWeTheSame(list) {
var sample = list[0];
return !(list.some(function(item) {
return !(item == sample);
}));
}
这很简单。创建一个函数并传递一个参数。在该函数中,将第一个索引复制到新变量中。然后创建一个for循环并遍历数组。在循环内部创建一个while循环,并使用条件检查新创建的变量是否等于循环中的所有元素。如果在for循环完成后其相等返回true,则在while循环内返回false。
function isUniform(arra){
var k=arra[0];
for (var i = 0; i < arra.length; i++) {
while(k!==arra[i]){
return false;
}
}
return true;
}
该接受的答案真是棒极了,但我想补充一点点。它对我来说不起作用,===
因为我正在比较对象数组的数组,但是在我的整个应用程序中,我一直在使用我强烈推荐的快速深相等包。这样,我的代码如下所示:
let areAllEqual = arrs.every((val, i, arr) => equal(val, arr[0]) );
我的数据如下所示:
[
[
{
"ID": 28,
"AuthorID": 121,
"VisitTypeID": 2
},
{
"ID": 115,
"AuthorID": 121,
"VisitTypeID": 1
},
{
"ID": 121,
"AuthorID": 121,
"VisitTypeID": 1
}
],
[
{
"ID": 121,
"AuthorID": 121,
"VisitTypeID": 1
}
],
[
{
"ID": 5,
"AuthorID": 121,
"VisitTypeID": 1
},
{
"ID": 121,
"AuthorID": 121,
"VisitTypeID": 1
}
]
]
function checkArray(array){
return array.join("") == array[0].repeat(array.length);
}
console.log('array: [a,a,a,a]: ' + checkArray(['a', 'a', 'a', 'a']));
console.log('array: [a,a,b,a]: ' + checkArray(['a', 'a', 'b', 'a']));
和你做!
您可以使用for循环:
function isEqual(arr) {
var first = arr[0];
for (let i = 1; i < arr.length; i++) {
if (first !== arr[i]) {
return false;
}
}
return true;
}
好吧,这确实不是很复杂。我非常怀疑您没有尝试。您要做的是选择第一个值,将其保存在变量中,然后在for
循环中将所有后续值与第一个值进行比较。
我故意不共享任何代码。查找如何for
使用以及如何比较变量。
使用ES6箭头函数语法时的另一种有趣方式:
x = ['a', 'a', 'a', 'a']
!x.filter(e=>e!==x[0])[0] // true
x = ['a', 'a', 'b', 'a']
!x.filter(e=>e!==x[0])[0] // false
x = []
!x.filter(e=>e!==x[0])[0] // true
并且当您不想为数组(x)重用变量时:
!['a', 'a', 'a', 'a'].filter((e,i,a)=>e!==a[0])[0] // true
IMO以前使用array.every(...)的海报提供了最干净的解决方案。
function isUniform(array) {
for (var i=1; i< array.length; i++) {
if (array[i] !== array[0]) { return false; }
}
for (var i=1; i< array.length; i++) {
if (array[i] === array[0]) { return true; }
}
}
这可能可行,您也可以使用注释掉的代码,这对于给定的scenerio也可以正常工作。
function isUniform(){
var arrayToMatch = [1,1,1,1,1];
var temp = arrayToMatch[0];
console.log(temp);
/* return arrayToMatch.every(function(check){
return check == temp;
});*/
var bool;
arrayToMatch.forEach(function(check){
bool=(check == temp);
})
console.log(bool);
}
isUniform();
分隔大小和组织列表的另一种方法:
array1 = [1,2,3]; array2 = [1,2,3];
function isEqual(){
return array1.toString()==array2.toString();
}
在PHP中,有一个非常简单的解决方案,即一行方法:
(count(array_count_values($ array))== 1)
例如 :
$arr1 = ['a', 'a', 'a', 'a'];
$arr2 = ['a', 'a', 'b', 'a'];
print (count(array_count_values($arr1)) == 1 ? "identical" : "not identical"); // identical
print (count(array_count_values($arr2)) == 1 ? "identical" : "not identical"); // not identical
就这样。