`map!':为String调用的私有方法(NoMethodError)

时间:2018-06-14 00:22:39

标签: ruby

我尝试编写一个私有函数,它将接受一个令牌并返回给定的令牌而没有空格或标点符号,例如:

normalize_token(" cat.")
# => "cat"

然后我定义了一个带标点符号和空格的标记数组:

["a.", "      b...."]

我想使用我定义的函数进行映射。我希望返回一个新对象,如下所示:

["a", "b"]

以下是一小段代码:

private def normalize_token(token)
  token.gsub(/\W/, ' ') # does the same thing as [^A-Za-z0-9_]
end

["a.", "      b...."].map!(&:normalize_token)

我明白了:

  

map!': private method normalize_token'呼吁" a。":字符串   (NoMethodError)

我将非常感谢您对我做错的任何帮助甚至解释。

2 个答案:

答案 0 :(得分:2)

不是传递方法引用,而是传递一个块:

private def normalize_token(token)
  token.gsub(/\W/, ' ') # does the same thing as [^A-Za-z0-9_]
end

["a.", "      b...."].map! {|token| normalize_token token}

这会在字符串中留下空白区域,因此您可能需要chomp!他们或将gsub更改为gsub(/\w/, '')

<强>解释

第一个问题是normalize_token是私有的。您可以通过公开或send将其作为@alex提及来解决这个问题。

然而,第二个问题更为微妙。

通过传递方法参考,您基本上有以下

["a.", "      b...."].map! {|token| token.send :normalize_token }

运行此命令将导致以下错误消息:

ArgumentError (wrong number of arguments (given 0, expected 1))

map!不会将映射值作为参数传递给normalize_token。 (请注意send将您的映射值作为接收器而不是参数。)相反,通过使用带有声明变量的块,我们可以通过在块中显式传递映射值作为参数来解决这个问题。

答案 1 :(得分:1)

关于&:的快速说明 - 它通过使用&amp;成就与{|i| ...}完成相同的事情。在:object上调用to_proc,然后将其作为块传递给方法 - 因此为了使用它,需要在传递给&:的任何对象上定义map!后面的任何内容。< / p>

这是一个例子,打开String类来定义它:

class String
  def normalize_token
    self.gsub(/\W/, ' ')
  end
end

这将允许您使用原始["a.", " b...."].map!(&:normalize_token)。 在现实生活中做这样的事情并不是一个好主意,因为你可能希望在任何负责生成这些字符串的类中定义normalize_token。但它应该让你开始。