24

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.

InputUsername
  • 390
  • 1
  • 3
  • 12

7 Answers7

33

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
Luan Nico
  • 5,376
  • 2
  • 30
  • 60
  • Imho it should be exactly 1. If it is smaller it depends on your semantics. Does an empty array have all elements equal? ;) – nathanvda Dec 14 '14 at 16:27
  • 4
    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. – Luan Nico Dec 14 '14 at 16:46
17

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]
SHS
  • 7,651
  • 3
  • 18
  • 28
5

Using Enumerable#each_cons:

def all_equal?(xs)
  xs.each_cons(2).all? { |x, y| x == y }
end
tokland
  • 66,169
  • 13
  • 144
  • 170
2

This works on Ruby 3.0+:

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

Looks pretty. Might not be the fastest though.

ouflak
  • 2,458
  • 10
  • 44
  • 49
sreedev
  • 51
  • 1
  • 5
1

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

  • 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. – InputUsername Dec 14 '14 at 16:37
  • 2
    Order an array just to check if all elements are unique is not efficient. – sidney Oct 03 '18 at 14:36
1

Try This ..

array = ["cars","cars","truck", nil]
array.uniq.compact.length == 1
Arvind singh
  • 1,312
  • 15
  • 15
0

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

[5, 5, 5].all?(5) # => true
Joel
  • 61
  • 3