本文简要介绍ruby语言中 Enumerable.sort_by
的用法。
用法
sort_by {|element| ... } → array
sort_by → enumerator
给定一个块,返回一个元素数组 self
,根据块为每个元素返回的值排序。相等元素的顺序是不确定的并且可能是不稳定的。
例子:
a = %w[xx xxx x xxxx]
a.sort_by {|s| s.size } # => ["x", "xx", "xxx", "xxxx"]
a.sort_by {|s| -s.size } # => ["xxxx", "xxx", "xx", "x"]
h = {foo: 2, bar: 1, baz: 0}
h.sort_by{|key, value| value } # => [[:baz, 0], [:bar, 1], [:foo, 2]]
h.sort_by{|key, value| key } # => [[:bar, 1], [:baz, 0], [:foo, 2]]
如果没有给出块,则返回 Enumerator
。
sort_by
的当前实现生成一个包含原始集合元素和映射值的元组数组。这使得 sort_by
在键集很简单时相当昂贵。
require 'benchmark'
a = (1..100000).map { rand(100000) }
Benchmark.bm(10) do |b|
b.report("Sort") { a.sort }
b.report("Sort by") { a.sort_by { |a| a } }
end
产生:
user system total real Sort 0.180000 0.000000 0.180000 ( 0.175469) Sort by 1.980000 0.040000 2.020000 ( 2.013586)
但是,请考虑比较 key 是一项重要操作的情况。以下代码使用基本的 sort
方法对修改时间的一些文件进行排序。
files = Dir["*"]
sorted = files.sort { |a, b| File.new(a).mtime <=> File.new(b).mtime }
sorted #=> ["mon", "tues", "wed", "thurs"]
这种排序效率低下:它在每次比较期间生成两个新的 File
对象。更好的技术是使用 Kernel#test
方法直接生成修改时间。
files = Dir["*"]
sorted = files.sort { |a, b|
test(?M, a) <=> test(?M, b)
}
sorted #=> ["mon", "tues", "wed", "thurs"]
这仍然会生成许多不必要的 Time
对象。一种更有效的技术是在排序之前缓存排序键(在这种情况下是修改时间)。 Perl 用户经常将这种方法称为 Schwartzian 变换,以 Randal Schwartz 命名。我们构建了一个临时数组,其中每个元素都是一个包含排序键和文件名的数组。我们对这个数组进行排序,然后从结果中提取文件名。
sorted = Dir["*"].collect { |f|
[test(?M, f), f]
}.sort.collect { |f| f[1] }
sorted #=> ["mon", "tues", "wed", "thurs"]
这正是 sort_by
在内部所做的。
sorted = Dir["*"].sort_by { |f| test(?M, f) }
sorted #=> ["mon", "tues", "wed", "thurs"]
要产生特定顺序的反向,可以使用以下命令:
ary.sort_by { ... }.reverse!
相关用法
- Ruby Enumerable.sort用法及代码示例
- Ruby Enumerable.slice_before用法及代码示例
- Ruby Enumerable.sum用法及代码示例
- Ruby Enumerable.slice_after用法及代码示例
- Ruby Enumerable.slice_when用法及代码示例
- Ruby Enumerable.select用法及代码示例
- Ruby Enumerable.any?用法及代码示例
- Ruby Enumerable.uniq用法及代码示例
- Ruby Enumerable.find_all用法及代码示例
- Ruby Enumerable.max用法及代码示例
- Ruby Enumerable.map用法及代码示例
- Ruby Enumerable.min_by用法及代码示例
- Ruby Enumerable.find_index用法及代码示例
- Ruby Enumerable.minmax用法及代码示例
- Ruby Enumerable.drop用法及代码示例
- Ruby Enumerable.member?用法及代码示例
- Ruby Enumerable.each_cons用法及代码示例
- Ruby Enumerable.entries用法及代码示例
- Ruby Enumerable.flat_map用法及代码示例
- Ruby Enumerable.reject用法及代码示例
- Ruby Enumerable.each_with_index用法及代码示例
- Ruby Enumerable.filter_map用法及代码示例
- Ruby Enumerable.all?用法及代码示例
- Ruby Enumerable.take用法及代码示例
- Ruby Enumerable.reduce用法及代码示例
注:本文由纯净天空筛选整理自ruby-lang.org大神的英文原创作品 Enumerable.sort_by。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。