322

I need to find arrays where all values are equal. What's the fastest way to do this? Should I loop through it and just compare values?

['a', 'a', 'a', 'a'] // true
['a', 'a', 'b', 'a'] // false
Marvin3
  • 5,741
  • 8
  • 37
  • 45
  • 1
    @T.J.Crowder I bet you are already thinking about the best solution ;) – VisioN Feb 12 '13 at 12:31
  • 4
    @T.J.Crowder: Not to mention the willingness of askers to actually accept answers. Users with 1 rep often seem to be ask & run types that leave as soon as they have a copy-paste-able answer, lately. – Cerbrus Feb 12 '13 at 12:39
  • Very right things you say here. But stackoverflow is very vulnerable to easy to ask questions. Just check out the top votes page. – Tomáš Zato Feb 12 '13 at 12:42
  • 1
    Something around this approach should work ? `a.join(',').split(a[0]).length === a.length + 1` – Jashwant Feb 12 '13 at 12:42
  • @Jashwant: Very clever! Although that'll only work with strings, or if you don't mind `1` to equal `'1'`. I'd upvote it if it were an answer, though ;-) – Cerbrus Feb 12 '13 at 12:46
  • I upvoted the comment at least. This is almost as awesome as that `JSON.stringify` comparison solution someone has posted (and deleted) here. – Tomáš Zato Feb 12 '13 at 12:51
  • Both arrays of OP has strings only. I was thinking that there's much easier approach. Let me put this as answer. Someone else can make it better. – Jashwant Feb 12 '13 at 12:51
  • This is a bit out of topic, but wrom what words the "OP" shortcut consists? I know it means answer, but I don't understand... – Tomáš Zato Feb 12 '13 at 13:15
  • 2
    @TomášZato: "OP" means "original poster" (the person asking the question). – T.J. Crowder Feb 12 '13 at 14:38
  • 2
    Possible duplicate of [Check if each item in an array is identical in javascript](http://stackoverflow.com/questions/9646943/check-if-each-item-in-an-array-is-identical-in-javascript) – Anderson Green Feb 14 '17 at 04:32
  • First of all, this is an exact dupe. Second, the `Array#every` answer in original question (the best answer for current state of browsers) is already there, then here we see all kinds of crazy solutions except for golopot's. What the heel is going on here?!! – Andre Figueiredo Jul 28 '18 at 01:18
  • I fancy `JSON.stringify(arr1) === JSON.stringify(arr2) ` – Tendai Nov 25 '18 at 21:56

33 Answers33

533
const allEqual = arr => arr.every( v => v === arr[0] )
allEqual( [1,1,1,1] )  // true

Or one-liner:

[1,1,1,1].every( (val, i, arr) => val === arr[0] )   // true

Array.prototype.every (from MDN) : The every() method tests whether all elements in the array pass the test implemented by the provided function.

Mamun
  • 66,969
  • 9
  • 47
  • 59
golopot
  • 10,726
  • 6
  • 37
  • 51
115

Edit: Be a Red ninja:

!!array.reduce(function(a, b){ return (a === b) ? a : NaN; });

Results:

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" 

Warning:

var array = [] => result: TypeError thrown

This is because we do not pass an initialValue. So, you may wish to check array.length first.

AndrewL64
  • 15,794
  • 8
  • 47
  • 79
Martin
  • 3,509
  • 3
  • 26
  • 31
  • 1
    +1 I tried to come up with a `reduce` version of this myself but didn't succeed. This is pretty cool. – dan-lee Oct 15 '14 at 07:10
  • 5
    might be a bit late to the party... i think this doesn't work if your array is made of `false`s! for example try [false, false, false].reduce(function(a, b){return (a === b)?a:false;}); – George Flourentzos Nov 27 '14 at 19:21
  • Small change: arr.reduce(function(a, b){return (a === b)?a:false;}) === arr[0]; – Martin Feb 09 '15 at 23:26
  • 1
    @Martin This won't work either... check with [false, false, true] array (will return true) – average Joe Jun 22 '15 at 09:01
  • 3
    @Martin: `["false", ""]` returns `true` :/ – dalgard Oct 15 '15 at 16:55
  • 6
    This can be taken up a notch by using `NaN`. Since both `NaN === NaN` and `NaN !== NaN` are false, it guarantees that once the `prev` is set to NaN then no value can take it out. Also adding in a double negation converts the results to `true` and `false`, since `NaN` is falsy. Final form: `!!array.reduce(function(a, b){ return (a === b) ? a : NaN; });` – Filipe Silva Jan 19 '16 at 17:53
  • Very good indeed. Original code updated to use NaN instead of false. – Martin Jan 21 '16 at 13:33
  • 1
    Nice solution, though it means that the entire array is always checked, even when only the beginning is required. – Quentin Roy Mar 22 '16 at 02:52
  • `[null, null]` evals to `false`. How about using `Symbol()` which is guaranteed to be different from any other value and then do a: `arr[0]===arr.reduce( function(accum,curr) { if (accum===curr) return curr; else return Symbol(); } )` – Marcus Junius Brutus Jul 22 '16 at 15:17
  • like said before, `[null, null]` evals to `false`. Personally I don't like the `new Symbol()` approach. What about this: ```const a = [null, null]; a[0] === a.reduce((a,b) => _.isEqual(a,b) ? a : NaN); // => true ``` – Omar Enrico Polo Sep 08 '16 at 13:00
  • 7
    **DOWNVOTED**. What if the elements are equal but **_falsy_**? – Константин Ван Jan 25 '18 at 09:52
  • 4
    I downvoted because this doesn't work with booleans values. – Tyguy7 Apr 03 '18 at 22:10
  • 1
    It is so easy to break it with the following input: `[false, false]`, `[0, 0]`, `[null, null]` and so on. If you must use reduce, pass an object containing previous value and a cumulative result. – Salman A Jul 08 '18 at 21:08
  • The easiest way to use `.reduce` here is to just compare each element with the first element and keep ANDing with the previous results `arr.reduce((res, el, i, arr) => res && el === arr[i], true)` no need to throw in random other values. However, that's still basically re-doing an `every`, so why bother? – VLAZ Nov 13 '20 at 16:04
72

You can turn the Array into a Set. If the size of the Set is equal to 1, then all elements of the Array are equal.

function allEqual(arr) {
  return new Set(arr).size == 1;
}

allEqual(['a', 'a', 'a', 'a']); // true
allEqual(['a', 'a', 'b', 'a']); // false
Huy Tran
  • 1,770
  • 3
  • 21
  • 41
65

This works. You create a method on Array by using prototype.

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

Call this in this way:

let a = ['a', 'a', 'a'];
let b = a.allValuesSame(); // true
a = ['a', 'b', 'a'];
b = a.allValuesSame();     // false
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
Robert Fricke
  • 3,637
  • 21
  • 34
  • 5
    very nice, but beware: IE does not support this way of assigning prototypes. I use it anyway. – Tomáš Zato Feb 12 '13 at 12:34
  • You don't need the `else` block in there, because the `if` will return a value from the function, before the code below it has a chance to be executed, if the condition in the `if` is `true`. If it's `false`, the `else` should be executed any way, no need to wrap it in extra `{}`'s – Cerbrus Feb 12 '13 at 12:43
  • 6
    @TomášZato: IE supports augmenting the `Array.prototype` just fine (even IE6). It's only DOM element prototypes that some older versions of IE don't support augmenting. – T.J. Crowder Feb 12 '13 at 13:00
  • @T.J. Crowder: Ah, thank you and sorry for my missinformation. – Tomáš Zato Feb 12 '13 at 13:02
  • 6
    I don't think it's a good idea to be monkey patching built-in prototypes. If multiple libraries do it, it can lead to unexpected behavior that's very difficult to debug. – Mark Wilbur Dec 12 '14 at 07:33
  • @MarkWilbur So build it as a global function `function allValuesSame(arr)` – Robert Fricke Dec 19 '14 at 13:45
  • 1
    @MarkWilbur +1 especially if you do a for..in loop on next arrays, you'll get `allValuesSame` in the loop – Olivier Pons Apr 23 '16 at 09:14
  • 1
    I went ahead and modernized this, without altering the intent. – Mr. Polywhirl Jan 08 '20 at 19:36
32

In JavaScript 1.6, you can use Array.every:

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

You probably need some sanity checks, e.g. when the array has no elements. (Also, this won't work when all elements are NaN since NaN !== NaN, but that shouldn't be an issue... right?)

Mattias Buelens
  • 19,609
  • 4
  • 45
  • 51
17

And for performance comparison I also did a benchmark:

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

Results:

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)

So apparently using builtin array.some() is the fastest method of the ones sampled.

Martin
  • 3,509
  • 3
  • 26
  • 31
  • 3
    Good idea to check what's more performant here. The reason why `Array#some` is going to sometimes outperform is that once the callback function returns true, it stops iterating. So, if all the elements are in fact equal, the performance should be identical to `Array#every`. And the relative performance when all elements are not equal will vary based on the index of the first non-matching element. – danmactough Jan 06 '15 at 12:09
  • 3
    Nice one. You could have named each with the function used lol. E.g.: reduce, filter, every, some – Bernardo Dal Corno Aug 02 '17 at 15:54
  • 1
    where s the native for loop, I bet that outperforms all of these by a factor of 5 – PirateApp May 11 '19 at 15:57
  • @Martin - where do you usually run performance checks? – Reena Verma Sep 02 '22 at 12:31
12

update 2022 version: use Set()

     let a = ['a', 'a', 'b', 'a'];
     let b = ['a', 'a', 'a', 'a'];
     const check = (list) => {
        const setItem = new Set(list);
        return setItem.size <= 1;
     }

     const checkShort = (list) => (new Set(list)).size <= 1        
     
      check(a); // false;
      check(b); // true;
      checkShort(a); // false
      checkShort(b); // true

Update new solution: check index

 let a = ['a', 'a', 'b', 'a'];
 let b = ['a', 'a', 'a', 'a'];
 let check = (list) => list.every(item => list.indexOf(item) === 0);
 check(a); // false;
 check(b); // true;
   

Updated with ES6: Use list.every is the fastest way:

 let a = ['a', 'a', 'b', 'a'];
 let check = (list) => list.every(item => item === list[0]);
   

old version:

      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));
      }
Kai
  • 3,104
  • 2
  • 19
  • 30
  • using `every` is the best solution. i especially like it because it'll stop the iteration as soon as it finds a falsy value (according to the MDN docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every#description) – greenie-beans May 02 '23 at 16:40
10

Shortest answer using underscore/lodash

function elementsEqual(arr) {
    return !_.without(arr, arr[0]).length
}

spec:

elementsEqual(null) // throws error
elementsEqual([]) // true
elementsEqual({}) // true
elementsEqual([1]) // true
elementsEqual([1,2]) // false
elementsEqual(NaN) // true

edit:

Or even shorter, inspired by Tom's answer:

function elementsEqual2(arr) {
    return _.uniq(arr).length <= 1;
}

spec:

elementsEqual2(null) // true (beware, it's different than above)
elementsEqual2([]) // true
elementsEqual2({}) // true
elementsEqual2([1]) // true
elementsEqual2([1,2]) // false
elementsEqual2(NaN) // true
average Joe
  • 4,377
  • 2
  • 25
  • 23
10

If you're already using underscore.js, then here's another option using _.uniq:

function allEqual(arr) {
    return _.uniq(arr).length === 1;
}

_.uniq returns a duplicate-free version of the array. If all the values are the same, then the length will be 1.

As mentioned in the comments, given that you may expect an empty array to return true, then you should also check for that case:

function allEqual(arr) {
    return arr.length === 0 || _.uniq(arr).length === 1;
}
Tom Fenech
  • 72,334
  • 12
  • 107
  • 141
8

every() function check if all elements of an array

    const checkArr = a => a.every( val => val === a[0] )
    checkArr(['a','a','a'])  // true 
     
Ashish Mishra
  • 412
  • 4
  • 5
6

You can use Array.every if supported:

var equals = array.every(function(value, index, array){
    return value === array[0];
});

Alternatives approach of a loop could be something like sort

var temp = array.slice(0).sort();
var equals = temp[0] === temp[temp.length - 1];

Or, if the items are like the question, something dirty like:

var equals = array.join('').split(array[0]).join('').length === 0;

Also works.

ZER0
  • 24,846
  • 5
  • 51
  • 54
  • You have the first example backwards. Should be `equals = !array.some( (v,i,a) => v!==a[0] )`. Otherwise you're just checking that any value equals the first which will, of course, always be true :) –  Jul 30 '15 at 04:53
  • Not exactly, I used `some` instead of `every` as I mentioned in the first paragraph. :) Thanks for the catch! – ZER0 Aug 02 '15 at 15:39
6

Yes, you can check it also using filter as below, very simple, checking every values are the same as the first one:

//ES6
function sameValues(arr) {
  return arr.filter((v,i,a)=>v===a[0]).length === arr.length;
} 

also can be done using every method on the array:

//ES6
function sameValues(arr) {
  return arr.every((v,i,a)=>v===a[0]);
} 

and you can check your arrays like below:

sameValues(['a', 'a', 'a', 'a']); // true
sameValues(['a', 'a', 'b', 'a']); // false

Or you can add it to native Array functionalities in JavaScript if you reuse it a lot:

//ES6
Array.prototype.sameValues = Array.prototype.sameValues || function(){
 this.every((v,i,a)=>v===a[0]);
}

and you can check your arrays like below:

['a', 'a', 'a', 'a'].sameValues(); // true
['a', 'a', 'b', 'a'].sameValues(); // false
Alireza
  • 100,211
  • 27
  • 269
  • 172
5

You can get this one-liner to do what you want using Array.prototype.every, Object.is, and ES6 arrow functions:

const all = arr => arr.every(x => Object.is(arr[0], x));
Noor
  • 191
  • 2
  • 7
5

Now you can make use of sets to do that easily.

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);
Krishnadas PC
  • 5,981
  • 2
  • 53
  • 54
4

I think the simplest way to do this is to create a loop to compare the each value to the next. As long as there is a break in the "chain" then it would return false. If the first is equal to the second, the second equal to the third and so on, then we can conclude that all elements of the array are equal to each other.

given an array data[], then you can use:

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

You can convert array to a Set and check its size

In case of primitive array entries, i.e. number, string:

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

In case of array of objects with some field to be tested for equivalence, say id:

const mapper = ({id}) => id
const isArrayWithEqualEntries = array => new Set(array.map(mapper)).size === 1
Simon
  • 158
  • 1
  • 7
2

You can use this:

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

The function first checks whether the array is empty. If it is it's values are equals.. Otherwise it filter the array and takes all elements which are different from the first one. If there are no such values => the array contains only equal elements otherwise it doesn't.

Minko Gechev
  • 25,304
  • 9
  • 61
  • 68
2
arr.length && arr.reduce(function(a, b){return (a === b)?a:false;}) === arr[0];
Joel Mueller
  • 28,324
  • 9
  • 63
  • 88
Martin
  • 3,509
  • 3
  • 26
  • 31
2

Its Simple. Create a function and pass a parameter. In that function copy the first index into a new variable. Then Create a for loop and loop through the array. Inside a loop create an while loop with a condition checking whether the new created variable is equal to all the elements in the loop. if its equal return true after the for loop completes else return false inside the while loop.

function isUniform(arra){
    var k=arra[0];
    for (var i = 0; i < arra.length; i++) {
        while(k!==arra[i]){
            return false;
        }
    }
    return true;
}
2

The accepted answer worked great but I wanted to add a tiny bit. It didn't work for me to use === because I was comparing arrays of arrays of objects, however throughout my app I've been using the fast-deep-equal package which I highly recommend. With that, my code looks like this:

let areAllEqual = arrs.every((val, i, arr) => equal(val, arr[0]) );

and my data looks like this:

[  
  [
    {
      "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
    }
  ]
]
2

You could use a for loop:

function isEqual(arr) {
  var first = arr[0];
  for (let i = 1; i < arr.length; i++) {
    if (first !== arr[i]) {
      return false;
    }
  }
  return true;
}
Armando Guarino
  • 1,120
  • 1
  • 5
  • 16
1

Underscore's _.isEqual(object, other) function seems to work well for arrays. The order of items in the array matter when it checks for equality. See http://underscorejs.org/#isEqual.

Jon Onstott
  • 13,499
  • 16
  • 80
  • 133
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);
    }));
}
antonio
  • 18,044
  • 4
  • 45
  • 61
1
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; }
  }
}
  • For the first loop; whenever it detects uneven, returns "false"
  • The first loop runs, and if it returns false, we have "false"
  • When it's not return false, it means there will be true, so we do the second loop. And of course we will have "true" from the second loop (because the first loop found it's NOT false)
user2321864
  • 2,207
  • 5
  • 25
  • 35
Jaden Tran
  • 13
  • 5
1
  1. Create a string by joining the array.
  2. Create string by repetition of the first character of the given array
  3. match both strings

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

And you are DONE !

Rahul Vala
  • 695
  • 8
  • 17
  • I use this to compare whether two arrays have the same elements in the same order and it works great. – fantom Jul 11 '22 at 17:59
0

Another interesting way when you use ES6 arrow function syntax:

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

And when you don't want to reuse the variable for array (x):

!['a', 'a', 'a', 'a'].filter((e,i,a)=>e!==a[0])[0]    // true

IMO previous poster who used array.every(...) has the cleanest solution.

0

this might work , you can use the comment out code as well that also woks well with the given 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

Use index of operator for every item of array to check if it exists or not. If even one item returns -1 (doesn't exist then it will be false)

nst arr1 = [1, 3, 5];
const arr2 = [5, 7, 9];
const arr3 = [1, 3, 5];

arr1.every(item => arr2.indexOf(item) != -1)
// this will return false

arr1.every(item => arr3.indexOf(item) != -1)
// this will return true
Baraja Swargiary
  • 381
  • 2
  • 10
-1

Simple one line solution, just compare it to an array filled with the first entry.

if(arr.join('') === Array(arr.length).fill(arr[0]).join(''))
BrokenBinary
  • 7,731
  • 3
  • 43
  • 54
pyviet
  • 9
  • 3
  • That doesn't seem like a solution that can be used anywhere – Lu4 Sep 22 '16 at 10:05
  • It's pretty close to ok. Better would be something like: function arrayOfSame(arr) { return (arr.join('') == (new Array(arr.length+1).join(arr[0]))); } – Arkain Mar 15 '17 at 15:57
-1
**// Logical Solution:- Declare global array and one variable(To check the condition) whether all element of an array contains same value or not.**

    var arr =[];
    var isMatching = false;

    for(var i=0;i<arr.length;i++){
            if(String(arr[i]).toLowerCase()== "Your string to check"){
                isMatching=true;
                // Array has same value in all index of an array
            }
            else{
                isMatching=false;
                // Array Doesn't has same value in all index of an array
                break;
            }
        }
    // **Check isMatching variable is true or false**

        if(isMatching){ // True
            //If Array has same value in all index, then this block will get executed
        }
        else{ //False
            //If Array doesn't has same value in all index, then this block will get executed
        }
-1

You could count the number of distinct values in the array, if this value is 1 all the entries are the same.

Example:

array = np.array([1, 2, 2, 3, 3])
set(array) # this gives the different values present in the array (1,2,3)
len(set(array)) # this returns 3, 3 different values in the array
-2

another cool solution i like is using XOR operator :

console.log([5,5,5,5].reduce((a,b)=>a^b) == 0)
>> true
console.log([5,5,5,4].reduce((a,b)=>a^b) == 0)
>> false
-5

In PHP, there is a solution very simple, one line method :

(count(array_count_values($array)) == 1)

For example :

$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

That's all.

Jerry
  • 1,141
  • 1
  • 13
  • 18