29

I'm having a bit of a 'problem' with Ruby code. I want to check if all elements of an array are equal.

For example, say I have an array of only 5s:

arr = [5, 5, 5, 5, 5]

I know I can do something like

arr[0] == arr[1] == arr[2] == arr[3] # == arr[4] == ...

but this is impossible for huge arrays and also not very Ruby-like in my opinion. We can improve it by doing something like this:

def all_equal?(arr)
  for i in 0..(arr.size-2)
    if arr[i] != arr[i+1] then
      return false
    end
  end
  true
end

But I also think this is pretty ugly. So is there any built-in/better/shorter (more Ruby-esque) way to do this?

TL;DR what is the shortest/most Ruby-esque way to check if an array contains only one distinct element (e.g. [5, 5, 5])?

Thanks.

2
  • If the elements of arr are all comparable with <=> you could do this: arr.min==arr.max, but this is clearly a job for uniq. Commented Dec 14, 2014 at 18:45
  • arr[0] == arr[1] == arr[2] Really? What Ruby version are you using? Commented Aug 9, 2017 at 13:49

8 Answers 8

39

You could also use .uniq, that returns an array with no duplicates, and check the size:

def all_equal?(arr)
    arr.uniq.size <= 1
end
Sign up to request clarification or add additional context in comments.

2 Comments

Imho it should be exactly 1. If it is smaller it depends on your semantics. Does an empty array have all elements equal? ;)
Indeed it is open to interpretation - for me an empty array has all elements equal, because it has no elements :) And it is not very efficient indeed, the better way would be the for. But often we exchange speed with prettiness in ruby, as these kind of operations are rarely the bottleneck in most applications.
20

Couple of ways.

The best one:

array.uniq.count <= 1 # or == 1 if it can't be an empty array

And:

array == ([array.first] * array.count)

And:

(array | array).count <= 1 # basically doing the same thing as uniq

Also:

array.reduce(:|) == array.first # but not very safe

And if it's a sortable array, then:

array.min == array.max    

And, just for sake of variety:

!array.any?{ |element| element != array[0] } # or array.first instead of array[0]

Alternatively:

array.all?{ |element| element == array[0] } # or array.first instead of array[0]

Comments

6

Using Enumerable#each_cons:

def all_equal?(xs)
  xs.each_cons(2).all? { |x, y| x == y }
end

1 Comment

Never knew that this kind of method existed in standard library. Thanks!
3

This works on Ruby 3.0+:

  [1,1,1,1].minmax.reduce(&:eql?)

Looks pretty. Might not be the fastest though.

Comments

2

Try This ..

array = ["cars","cars","truck", nil]
array.uniq.compact.length == 1

Comments

1

Sort the array and compare the first value to the last.

2 Comments

I like this solution. It does require that the array can be sorted/compared (which is not always the case), so I'm going to go with Luan Nico's answer.
Order an array just to check if all elements are unique is not efficient.
1

Looks like with later versions you can just pass matching argument to all? without a block

[5, 5, 5].all?(5) # => true

Comments

0

Apart from (generalized version of Joel's answer) arr.all?(arr.first) (which returns true for empty array), something like arr.reduce {|acc, x| x == acc ? x : (break false)} also works, returning the one value if all elements are equal or false if they are not equal. Only problem is if the array contains boolean values, then it's impossible to tell if they are all false or if they are different.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.