Более общее решение (хотя и не самое эффективное):
class EqualityWrapper
attr_reader :obj
def initialize(obj, eq, hash)
@obj = obj
@eq = eq
@hash = hash
end
def ==(other)
@eq[@obj, other.obj]
end
alias :eql? :==
def hash
@hash[@obj]
end
end
class Array
def uniq_by(eq, hash = lambda{|x| 0 })
map {|x| EqualityWrapper.new(x, eq, hash) }.
uniq.
map {|x| x.obj }
end
def uniq_ci
eq = lambda{|x, y| x.casecmp(y) == 0 }
hash = lambda{|x| x.downcase.hash }
uniq_by(eq, hash)
end
end
Метод uniq_by
принимает лямбду, которая проверяет равенство, и лямбду, которая возвращает хеш, и удаляет дублирующиеся объекты, как определено этими данными.
Кроме того, реализованный метод uniq_ci
удаляет дубликаты строк с использованием сравнения без учета регистра.