检查数组的所有值是否相等


188

我需要找到所有值都相等的数组。最快的方法是什么?我应该遍历它并只是比较值吗?

['a', 'a', 'a', 'a'] // true
['a', 'a', 'b', 'a'] // false

1
@TJCrowder我敢打赌,您已经在考虑最佳解决方案了;)
VisioN 2013年

2
@TJCrowder:更不用说问者愿意接受答案了。具有1个代表的用户通常似乎是询问并运行类型,它们最近在获得可复制粘贴的答案后就离开了。
Cerbrus

1
这种方法周围的东西应该起作用吗?a.join(',').split(a[0]).length === a.length + 1
Jashwant

1
@TomášZato:“ OP”的意思是“原始海报”(问问题的人)。
TJ Crowder

Answers:


286
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()方法测试数组中的所有元素是否通过提供的功能实现的测试。


10
简洁是机智的灵魂
svarog

1
我创建了一个jsperf案例。这种方法胜过大多数候选人。
黄俊亮

1
const everythings_equal = array => array.every(thing => thing === array[0]);
КонстантинВан

8
some代替everyarr.some( v => v !== arr[0] )。这将在第一个元素不等于时返回arr[0]
1

2
@Jan every也早早返回。
golopot

111

编辑:是红色忍者:

!!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


5
可能对聚会来说有点晚了...如果您的数组由falses 组成,我认为这是行不通的!例如try [false,false,false] .reduce(function(a,b){return(a === b)?a:false;});
George Flourentzos 2014年

3
@Martin:["false", ""]返回true:/
dalgard 2015年

6
可以使用来解决此问题NaN。由于NaN === NaNNaN !== NaN均为假,因此可以保证一旦将prev设置为NaN,则没有值可以将其取出。此外,添加双重否定会将结果转换为truefalse,因为这NaN是虚假的。最终形式:!!array.reduce(function(a, b){ return (a === b) ? a : NaN; });
Filipe Silva

3
下载。如果元素相等但虚假怎么
КонстантинВан

3
我拒绝投票,因为这不适用于布尔值。
Tyguy18年

62

这可行。您通过使用原型在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

5
非常好,但是请注意:IE不支持这种分配原型的方式。我还是用它。
托马什Zato -恢复莫妮卡

5
@TomášZato:IE支持扩展Array.prototype恰好(甚至是IE6)。某些早期版本的IE不支持扩充功能,这只是DOM元素原型。
TJ Crowder 2013年

4
我认为猴子修补内置原型不是一个好主意。如果使用多个库,则可能导致难以调试的意外行为。
马克·威尔伯2014年

1
@MarkWilbur +1尤其是如果您在下一个数组上执行for..in循环,您将陷入allValuesSame循环
Olivier Pons

1
我继续进行了现代化,并且没有改变意图。
Polywhirl先生

30

在JavaScript 1.6中,您可以使用Array.every

function AllTheSame(array) {
    var first = array[0];
    return array.every(function(element) {
        return element === first;
    });
}

您可能需要进行完整性检查,例如,当数组中没有元素时。(另外,这是不行的,当所有的元素都是NaN因为NaN !== NaN,但这不应该是一个问题,对吧?)


30

您可以将数组变成集合。如果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
КонстантинВан

12

为了进行性能比较,我还做了一个基准测试:

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()是采样方法中最快的方法。


3
检查这里性能更好的好主意。之所以Array#some有时会表现不佳,是因为一旦回调函数返回true,它就会停止迭代。因此,如果所有元素实际上都相等,则性能应与相同Array#every。当所有元素都不相等时的相对性能将根据第一个不匹配元素的索引而变化。
danmactough

3
好一个。您可能已使用函数lol命名了每个函数。例如:减少,过滤,过滤一些
Z. Khullah

在本地for循环中,我敢打赌,它们的性能
要比

9

使用下划线/破折号的最短答案

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

6

如果您已经在使用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;
}

但是,如果array为空,您的答案将返回false。虽然我认为应该如此true。更改为.length <= 1就足够了。
平均乔

@Kasztan,这很公平。我已经更新了答案以解决这种情况。
汤姆·费内奇

6

是的,您还可以使用以下过滤器对其进行检查,非常简单,检查每个值是否与第一个相同:

//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

5

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] )。否则,您只是在检查是否有任何值等于第一个值,当然,该值总是正确的:)
Mark Kahn 2015年

不完全是,我使用的some不是every我在第一段中提到的。:)感谢您的收获!
ZER0


3

我认为最简单的方法是创建一个循环,将每个值与下一个值进行比较。只要“链”中断,它就会返回false。如果第一个等于第二个,第二个等于第三个,依此类推,那么我们可以得出结论,数组的所有元素都相等。

给定数组data [],则可以使用:

for(x=0;x<data.length - 1;x++){
    if (data[x] != data[x+1]){
        isEqual = false;            
    }
}
alert("All elements are equal is " + isEqual);

3
arr.length && arr.reduce(function(a, b){return (a === b)?a:false;}) === arr[0];

3

更新新解决方案:检查索引

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

2

您可以使用此:

function same(a) {
    if (!a.length) return true;
    return !a.filter(function (e) {
        return e !== a[0];
    }).length;
}

该函数首先检查数组是否为空。如果是,则它们的值是相等的。否则,它将对数组进行过滤,并接受与第一个元素不同的所有元素。如果没有这样的值=>数组仅包含相等的元素,否则不包含。



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

还请解释您所做的事情,而不只是粘贴一些代码。
Wouter J 2015年

1

这很简单。创建一个函数并传递一个参数。在该函数中,将第一个索引复制到新变量中。然后创建一个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;
}

1

接受的答案真是棒极了,但我想补充一点点。它对我来说不起作用,===因为我正在比较对象数组的数组,但是在我的整个应用程序中,我一直在使用我强烈推荐的快速深相等包。这样,我的代码如下所示:

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

1
  1. 通过加入数组创建一个字符串。
  2. 通过重复给定数组的第一个字符来创建字符串
  3. 匹配两个字符串

	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']));

和你做!


1

现在,您可以使用集合轻松地做到这一点。

let a= ['a', 'a', 'a', 'a']; // true
let b =['a', 'a', 'b', 'a'];// false

console.log(new Set(a).size === 1);
console.log(new Set(b).size === 1);



0

好吧,这确实不是很复杂。我非常怀疑您没有尝试。您要做的是选择第一个值,将其保存在变量中,然后在for循环中将所有后续值与第一个值进行比较。
我故意不共享任何代码。查找如何for使用以及如何比较变量。


8
我不喜欢这个答案。它不会让您知道第二个值是否与第三个值相同,依此类推。显然,嵌套循环可以做到,但是从概念上讲,它与新手脚本编写器不同。
jtromans

3
@jtromans:由于相等的传递性,如果A == B和A == C,那么我们知道B == C;您不必使用嵌套循环等“手动”进行验证。针对单个值(数组中的第一个值,而不是任意一个:)重复比较正是此答案所建议的,接受的答案也是如此。
2013年

@ov确实,我急忙误读了这个问题,我认为当时所需要的不仅仅是检查所有值是否相等(!duh)。
jtromans

9
这并不复杂。页面上的其他答案也没有。但是对我来说,这个答案到目前为止最没有帮助。
查理

1
本来是要向OP强调自己坚持要在提出问题之前先思考的观点。
托马什Zato -恢复莫妮卡

0

简单的单行解决方案,只需将其与填充第一个条目的数组进行比较即可。

if(arr.join('') === Array(arr.length).fill(arr[0]).join(''))

这似乎不是可以在任何地方使用的解决方案
Lu4

差不多可以了。更好的是这样的:function arrayOfSame(arr){return(arr.join('')==(new Array(arr.length + 1).join(arr [0])));; }
Arkain

0

使用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(...)的海报提供了最干净的解决方案。


0
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; }
  }
}
  • 对于第一个循环;只要检测到不均匀,就返回“ false”
  • 第一个循环运行,如果返回false,则为“ false”
  • 当它不返回false时,它意味着将为真,所以我们进行第二个循环。当然,我们将从第二个循环获得“ true”(因为第一个循环发现它不是false)

0

这可能可行,您也可以使用注释掉的代码,这对于给定的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();



0

您可以将数组转换为Set并检查其大小

在原始阵列条目的情况下,即numberstring

const isArrayWithEqualEntries = array => new Set(array).size === 1

对于具有某个要进行等效性测试的对象的数组,请说id

const mapper = ({id}) => id
const isArrayWithEqualEntries = array => new Set(array.map(mapper)).size === 1

-4

在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

就这样。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.