26

&我们经常使用符号上的符号来缩短块,如下所示:

some_array.group_by(&:foo)

有没有类似的方法来缩短表达式{|x| x}

some_array.group_by{|x| x}

如果有一个Object#self返回的方法self,那么我们可以做

some_array.group_by(&:self)

但不幸的是,没有这样的方法。就字符数而言,它可能会更长,但可读性会有所提高。

4

3 回答 3

30

的。#itself在 Ruby 2.2.0 中实现。


您可以在此处访问关于此功能的 Ruby 核心团队讨论。

作为一个有趣的类比,已经提出#ergo了该方法,该方法将使接收器产生给定的块。

如果您还没有升级到 Ruby 2.2.0,您可能希望向后移植#itself和/或定义#ergo如下:

class Object
  def itself; self end
  def ergo
    fail ArgumentError, "Block expected!" unless block_given?
    yield self
  end
end

接着:

some_array.group_by &:itself
于 2013-06-05T06:27:08.763 回答
18

好吧,据我所知,没有内置的,但你可以制作一个可重用的身份块:

id = Proc.new {|x| x}
some_array.group_by(&id)

然后,如果您真的希望这是一个语言功能:

class Object
  def it
    Proc.new {|x| x}
  end
end

然后你可以这样做:

some_array.group_by(&it)

任何你喜欢的地方。这可能会使您的保修失效。

于 2013-06-05T06:18:51.847 回答
14

是的!该方法Kernel#itself是在 Ruby 2.2.0 中添加的。这个方法只是返回它被调用的对象,所以你可以这样写:

some_array.group_by(&:itself)

您可以在此处查看有关此功能的广泛讨论: https ://bugs.ruby-lang.org/issues/6373 。该补丁由 Rafael França 在消息 #53 中提交。您可以通过查看object.c在官方 Ruby 源代码中看到它。

如果您使用的是早于 2.2.0 的 Ruby 版本,则可以Kernel#itself通过将此代码放在项目中的某个位置并确保它被需要来轻松添加到您的项目中:

module Kernel
  def itself
    self
  end
end if !Kernel.instance_methods.include?(:itself)

但是,像这样对 Ruby 核心的一部分进行猴子修补可能很危险,如果您正在制作可重用的代码(如 gem),我不建议您这样做。相反,我建议您按照 user2246674 的建议制作自己的身份功能:

module MyLibrary
  IDENT = Proc.new { |x| x }

  array.group_by(&IDENT)
end
于 2014-09-16T22:06:32.273 回答