为什么Dir.glob(" * .txt")。sort也需要.each?

时间:2016-12-20 17:56:05

标签: arrays ruby glob ruby-1.9.3

Dir.glob("*.txt") {|f| p f}打印文件名。

Dir.glob("*.txt").sort {|f| p f}因ArgumentError而失败。

Dir.glob("*.txt").sort.each {|f| p f}按字母顺序打印文件名。

为什么第二个失败?更好的是,为什么第一个工作,有或没有.each

  • Dir.globDir.glob.sort都是数组。
  • Dir.glob.methods == Dir.glob.sort.methods

(灵感来自Alphabetize results of Dir.glob。不是Dir.glob with sort issue的重复,因为第三个"已经回答了那个问题。)

2 个答案:

答案 0 :(得分:5)

第二个失败是因为sort {|f| p f}确实没有意义。与sort一起使用的块应该是"return -1, 0, or +1"并且接受两个参数(要比较的元素)但是你的块接受一个参数并返回该参数,因为p str返回str }。

第三个很好,因为sort的默认比较器块相当于说:

sort { |a, b| a <=> b }

所以.sort.each非常有意义。

如果您在第二个示例中使用sort期望的那种块:

Dir.glob("*.txt").sort {|a, b| a <=> b }
然后事情会好起来的。或者如果你想按升序的词汇顺序对事物进行排序,你可以省略一块:

Dir.glob('*.txt').sort

答案 1 :(得分:4)

另一个答案是正确的,但我认为有更深层次的解释。当您在方法调用之后有一个块时,如Dir.glob("*.txt") {|f| p f},该块是该方法的(可选)参数。在Dir.glob的定义中,有一个运行块的yield语句。

当你链接方法时,就像在Dir.glob("*.txt").sort {|f| p f}中一样,该块成为sort方法的参数,而不是glob方法。 sort也可以使用块来定义比较,但是在这种情况下这个块没有意义。

链接each以获取Dir.glob("*.txt").sort.each {|f| p f}使得该块成为each方法的参数,该方法像glob一样使用它(为每个参数运行块)。