在Ruby中对字符串数组进行排序

poo*_*ank 22 ruby arrays sorting

我在Ruby中学到了两种数组排序方法:

array = ["one", "two", "three"]
array.sort.reverse!
Run Code Online (Sandbox Code Playgroud)

要么:

array = ["one", "two", "three"]
array.sort { |x,y| y<=>x }
Run Code Online (Sandbox Code Playgroud)

我无法区分这两者.哪种方法更好,它们在执行方面究竟有何不同?

tes*_*ssi 31

两条线都相同(创建一个新的数组,反向排序).主要论点是关于可读性和性能.array.sort.reverse!array.sort{|x,y| y<=>x}我更可读- 我想我们可以在这里达成一致.

对于性能部分,我创建了一个快速基准测试脚本,它在我的系统(ruby 1.9.3p392 [x86_64-linux])上给出了以下内容:

                              user     system      total        real
array.sort.reverse        1.330000   0.000000   1.330000 (  1.334667)
array.sort.reverse!       1.200000   0.000000   1.200000 (  1.198232)
array.sort!.reverse!      1.200000   0.000000   1.200000 (  1.199296)
array.sort{|x,y| y<=>x}   5.220000   0.000000   5.220000 (  5.239487)
Run Code Online (Sandbox Code Playgroud)

对于基准脚本的多次执行,运行时间非常稳定.

array.sort.reverse(有或没有!)比快array.sort{|x,y| y<=>x}.因此,我建议.


这是脚本作为参考:

#!/usr/bin/env ruby
require 'benchmark'

Benchmark.bm do|b|
  master = (1..1_000_000).map(&:to_s).shuffle
  a = master.dup
  b.report("array.sort.reverse      ") do
    a.sort.reverse
  end

  a = master.dup
  b.report("array.sort.reverse!     ") do
    a.sort.reverse!
  end

  a = master.dup
  b.report("array.sort!.reverse!    ") do
    a.sort!.reverse!
  end

  a = master.dup
  b.report("array.sort{|x,y| y<=>x} ") do
    a.sort{|x,y| y<=>x}
  end
end
Run Code Online (Sandbox Code Playgroud)


Jam*_*wer 6

这里真的没什么区别.两种方法都返回一个新数组.

出于此示例的目的,更简单更好.我建议array.sort.reverse因为它比替代方案更具可读性.将块传递给类似的方法sort应该保存为更复杂的数据结构和用户定义的类的数组.

编辑:虽然destructive方法(任何以!结尾的东西)对性能游戏都有好处,但有人指出它们不需要返回更新的数组,或者根本不需要返回任何内容.记住这array.sort.reverse!一点很重要,因为很可能会回来nil.如果您希望在新生成的数组上使用破坏性方法,则应该更喜欢.reverse!在单独的行上调用而不是使用单行.

例:

array = array.sort
array.reverse!
Run Code Online (Sandbox Code Playgroud)

应该优先考虑

array = array.sort.reverse!
Run Code Online (Sandbox Code Playgroud)

  • OP只是学习Ruby,在这个阶段不应该对性能如此苛刻.我支持我的建议. (4认同)
  • 了解性能永远不会太早:) (3认同)
  • 然而@JamesBrewer在使用先前排序创建的临时数组上调用破坏性反转是一种不好的做法.没有文件证明`reverse!`必须返回更新的数组.它只更新被调用对象.前者是非破坏性版本的任务. (3认同)