class Array
def indices_uniq
uniq.map { |e| index(e) }
end
end
arr = ["fun", "sun", 3, 5, 5, 5, 1, 2, 1, "fun"]
arr.indices_uniq
#=> [0, 1, 2, 3, 6, 7]
To see what's going on here, let's write this more verbosely and include some code to display intermediate values:
class Array
def indices_uniq
puts "self = #{self}"
arr = self
u = arr.uniq
puts "u = #{u}"
u.map { |e|
puts "#{e} is at index #{index(e)}"
arr.index(e) }
end
end
arr.indices_uniq
# self = ["fun", "sun", 3, 5, 5, 5, 1, 2, 1, "fun"]
# u = ["fun", "sun", 3, 5, 1, 2]
# fun is at index 0
# sun is at index 1
# 3 is at index 2
# 5 is at index 3
# 1 is at index 6
# 2 is at index 7
#=> [0, 1, 2, 3, 6, 7]
We can substitute out u
and arr
:
class Array
def indices_uniq
self.uniq.map { |e| self.index(e) }
end
end
arr.indices_uniq
#=> [0, 1, 2, 3, 6, 7]
The key: self
is the receiver for methods that do not have explicit receivers. In the last version of the methods uniq
and include
both have the explicit receiver self
. It follows that if the explicit receiver is removed, the receiver will still be self
:
class Array
def indices_uniq
uniq.map { |e| index(e) }
end
end
arr.indices_uniq
#=> [0, 1, 2, 3, 6, 7]
Another way of doing this is to change the operative line to:
map { |e| index(e) }.uniq