将自定义类的自定义方法传递到.map

时间:2015-07-06 12:14:52

标签: ruby proc

我正在为exerciseism.io进行练习 - 说明很长,与此问题无关,但您可以找到我的完整解决方案here

基本上我有一个Robot类和3个私有方法:

  def rand_letters
    ('A'..'Z').to_a[rand(26)]
  end

  def rand_numbers
    (0..9).to_a[rand(10)]
  end

我正在尝试将这些传递给另一个私有方法,如下所示:

  def set_name
    @name = ((1..2).map(&:rand_letters) + (3..5).map(&:rand_numbers)).join
  end

当我这样做时,我收到错误:undefined method 'rand_letters' for 1:Fixnum。看了this question之后我想也许问题是我的班级没有to_proc方法。不幸的是我不确定如何纠正这个问题。我尝试让我的类继承自Proc,但我仍然坚持如何覆盖to_proc。任何帮助我指向正确方向的人都会非常感激。

2 个答案:

答案 0 :(得分:2)

首先:您可以使用array.sample代替array[rand(x)]从数组中获取随机元素。

此外,您可以将(1..n).map替换为n.times.map

(2.times.map { rand_letters } + 3.times.map { rand_numbers }).join

但是使用map让我感到反直觉。如果我们可以简单地抓住3个随机字母,那会不会更容易?

这可以通过返回Enumerator而不是单个值来实现。复数命名已经表明rand_方法应该返回多个值:

def rand_letters
  return enum_for(__method__) unless block_given?
  loop { yield ('A'..'Z').to_a.sample }
end

def rand_numbers
  return enum_for(__method__) unless block_given?
  loop { yield (0..9).to_a.sample }
end

这允许我们拨打Enumerable#take

(rand_letters.take(2) + rand_numbers.take(3)).join
#=> "ZJ010"

或使用[...]文字:

[rand_letters.take(2), rand_numbers.take(3)].join

答案 1 :(得分:0)

以下是解决方案:

def rand_letters
  ('A'..'Z').to_a[rand(26)]
end

def rand_numbers
  (0..9).to_a[rand(10)]
end

p ((1..2).map { rand_letters } + (1..3).map { rand_numbers }).join

使用map(&:rand_letters)语法时,您会向集合的每个元素发送消息。在我们的情况下,Fixnum个对象接收消息(:rand_letters)并且无法响应该消息,因为它未在类Fixnum中定义

在我的示例中,消息:rand_letters:rand_numbers不会传递给Fixnum实例,而是传递给self,其中定义了thery。

以下是如何在课堂中使用它的方法:

class A
  def rand_letters
    ('A'..'Z').to_a[rand(26)]
  end

  def rand_numbers
    (0..9).to_a[rand(10)]
  end

  def name    
    (1..2).map { rand_letters } + (1..3).map { rand_numbers }.join
  end
end

A.new.name