本文簡要介紹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。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。