稳定#sort采取阻止

时间:2015-01-30 11:38:19

标签: ruby sorting

我们发现here是Ruby中一个稳定的sort_by的实现,它适用于一般情况(即我可以提供我自己的比较算法),而在this thread用户tokland描述了一种非常优雅的方式做一个稳定的sort_by:

module Enumerable 
  def stable_sort_by 
    sort_by.with_index { |x, idx| [yield(x), idx] } 
  end 
end

将Enumerator对象与 with_index 一起使用的想法非常简单!我想找到一个类似的优雅解决方案来创建一个稳定版本的#sort函数,它给出了一个比较块。它会像这样使用:

sorted_people = people.stable_sort do |person|
  person.name
end 

1 个答案:

答案 0 :(得分:2)

这是一个解决方案(但远非优雅):

module Enumerable
  def stable_sort
    each_with_index.sort { |(x, i), (y, j)|
      r = yield(x, y)
      r == 0 ? i <=> j : r
    }.map(&:first)
  end
end

它生成一个[element, index]对数组,并通过将每两个元素传递给给定块来对它们进行排序(就像sort那样)。如果块返回0,则比较索引,否则返回块的结果。然后,从生成的数组中提取元素。

示例:

arr = [[2, :baz], [1,:foo], [1, :bar]]

arr.sort { |x, y| x[0] <=> y[0] }
#=> [[1, :bar], [1, :foo], [2, :baz]]

arr.stable_sort { |x, y| x[0] <=> y[0] }
#=> [[1, :foo], [1, :bar], [2, :baz]]