如何覆盖Enumerables排序方法

时间:2016-05-03 18:30:22

标签: ruby

我正在尝试创建一个使用Enumerables的sort方法功能的方法。

想象一下,我有这个数据

data = [{project: 'proj', version: '1.1'}, {project: 'proj2', version: '1.11'}, {project: 'proj3', version: '1.2'}]

我希望能够像这样调用方法:

data.natural_sort{|a,b| b[:version] <=> a[:version] }

发生的实际调用会达到以下目的:

data.sort{|a,b|  MyModule.naturalize_str(b[:version]) <=> MyModule.naturalize_str(a[:version]) }

这是我当前破碎的代码:

Enumerable.module_eval do 

  def natural_sort(&block)
    if !block_given?
      block = Proc.new{|a,b| Rearmed.naturalize_str(a[:version]) <=> Rearmed.naturalize_str(b[:version])}
    end

    sort do |a,b| 
      a = Rearmed.naturalize_str(a)
      b = Rearmed.naturalize_str(b)
      block.call(a,b)
    end
  end

end

它会抛出一个错误,因为a和b是哈希而不是我想要的版本。

1 个答案:

答案 0 :(得分:3)

你在这里与自己发生冲突。在natural_sort块中,您期望哈希对象,但在实现中,您已明确将ab转换为字符串。

在Ruby中,有两种排序方式,sort方法与a,b对,以及sort_by方法,它使用中间排序形式进行比较。 sort_by方法通常明显更快,因为它将变换应用于每个对象一次,而sort方法每次进行比较时都会执行此操作。

这是重写:

def natural_sort_by(&block)
  if (block_given?)
    sort_by do |o|
      Rearmed.naturalize_str(yield(o))
    end
  else
    sort_by do |o|
      Rearmed.naturalize_str(o)
    end
  end
end

然后你可以这样称呼它:

data.natural_sort_by { |o| o[:version] }