I have implemented my own version of Ruby's Array uniq-method (Ruby docs - Class array) as a monkey patch on Array.
Method-impl.:
require 'set'
class Array
def own_uniq
uniq = Set.new
self.each { uniq.add(it) }
uniq.to_a
end
end
Usage:
require_relative "own_uniq.rb"
example = [1, 2, 4, 8, 16, 32, 1, 4, 16]
puts example.own_uniq.inspect # -> [1, 2, 4, 8, 16, 32]
Although it seems to work: Is my implementation generally correct?
Can it be improved? Respectively: Is there a better approach?
-
1\$\begingroup\$ The eternal debate about "what is monkey patching?" begs the question - do you intend to add a new method or replace the existing one? \$\endgroup\$radarbob– radarbob2025年07月20日 22:23:50 +00:00Commented Jul 20 at 22:23
-
\$\begingroup\$ It's meant as a new method. But actually the only motivation writing it, was to become more familiar with Ruby. By re-implementing it's own methods. \$\endgroup\$michael.zech– michael.zech2025年07月21日 08:23:48 +00:00Commented Jul 21 at 8:23
1 Answer 1
Your code can be simplified to the following:
require 'set'
class Array
def own_uniq
Set.new(self).to_a
end
end
Or even:
require 'set'
class Array
def own_uniq = Set.new(self).to_a
end
But a notable way in which your own_uniq method is not an adequate replacement for Array#uniq is that it does not permit the passing of a block to specify how to determine uniqueness as seen in the linked documentation.
An implementation that does might look like:
class Array
def own_uniq(&proc)
return Set.new(self).to_a unless proc
sort {
|a, b| proc.call(a) <=> proc.call(b)
}.each_with_object([]) { |x, set|
set << x if set.empty? || proc.call(x) != proc.call(set.last)
}
end
end
If calling proc can be non-trivial, you may wish to employ a Schwartzian transform approach in implementing own_uniq.