Ruby 中的猴子修补数组

Monkey Patching Arrays in Ruby

我将我自己的方法添加到数组 class 中,它与 Array#uniq 做同样的事情。

这是我的版本:

arr = ["fun", "sun", 3, 5, 5, 5, 1, 2, 1, "fun"]

class Array
    def my_uniq
        new_arr = []
        each do |item|
            new_arr << item unless new_arr.include?(item)
        end
        new_arr
    end
end

print arr.my_uniq

有没有办法将其修改为 return 唯一元素的索引而不是元素本身?

each_with_index 将允许您迭代数组和 return 索引。

each_with_index do |item, index|
  newArr << index unless newArr.include?(item)
end
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] 

为了看看这里发生了什么,让我们写得更详细一些,并包含一些代码来显示中间值:

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] 

我们可以替换掉uarr:

class Array
  def indices_uniq
    self.uniq.map { |e| self.index(e) }
  end
end

arr.indices_uniq
   #=> [0, 1, 2, 3, 6, 7]

关键:self是没有显式接收者的方法的接收者。在方法的最新版本中uniqinclude 都有明确的接收者 self。由此可见,如果显式接收者被移除,接收者仍然是self:

class Array
  def indices_uniq
    uniq.map { |e| index(e) }
  end
end

arr.indices_uniq
   #=> [0, 1, 2, 3, 6, 7]

另一种方法是将操作行更改为:

map { |e| index(e) }.uniq