如何在Ruby中生成随机名称

时间:2014-11-09 12:23:19

标签: ruby random-sample

我需要在ruby中创建一个程序来生成像KU765或NG274样式的机器人名称 并存储它们并检查它以避免重复。 我还需要制作一个“重置”方法来删除所有存储的名称并重新开始。 该程序由于某种原因不起作用。我希望有人帮助我找到错误。 非常感谢。

class Robot
  attr_accessor :named , :stored_names , :rl
  def self.name
    new.name
  end

  @@rl = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ"

  def name
    named = ""
    named << @@rl[rand(26).to_i]
    named << @@rl[rand(26).to_i]
    named << rand(100..999).to_s
    named.save_name 
    named.check_name
  end

  def save_name
    stored_names = []
    stored_names << named
  end

  def check_name
    stored_names.uniq!
  end

  def reset
    stored_names = Array.new
  end
end

5 个答案:

答案 0 :(得分:3)

这是构建您可能希望考虑的Robot课程的另一种方法。 (我的回答通常不长或详细,但我写这部分是为了在我自己的脑海中澄清Ruby对象模型的各个方面。我希望它可以帮助其他人做同样的事情。)

<强>代码

PREFACE      = ('A'..'Z').to_a << ?_
SUFFIX       = ('0'..'9').to_a
PREFACE_SIZE = 2
SUFFIX_SIZE  = 3

class Robot
  def self.reset()     @bots = []               end
  reset    
  def self.new()       (@bots << super).last    end
  def self.bots()      @bots                    end
  def self.delete(bot) @bots.delete(bot)        end
  def self.bot_names() @bots.map { |b| b.name } end

  attr_reader :name

  def initialize()     @name = add_name         end

  private

  def add_name
    loop do
      @name = gen_name 
      return @name unless self.class.bot_names.include?(@name)
    end
  end

  def gen_name
    PREFACE.sample(PREFACE_SIZE).join << SUFFIX.sample(SUFFIX_SIZE).join
  end
end

示例

Robot.bots           #=> []
robbie = Robot.new   #=> #<Robot:0x000001019f4988 @name="AP436">
robbie.name          #=> "AP436"
Robot.bots           #=> [#<Robot:0x000001019f4988 @name="AP436">]
r2d2 = Robot.new     #=> #<Robot:0x000001019cd450 @name="KL628">
r2d2.name            #=> "KL628"
Robot.bots           #=> [#<Robot:0x000001019f4988 @name="AP436">,
                     #   #<Robot:0x000001019cd450 @name="KL628">]
Robot.bot_names      #=> ["AP436", "KL628"]
Robot.delete(robbie) #=> #<Robot:0x000001019f4988 @name="AP436">
Robot.bots           #=> [#<Robot:0x000001019cd450 @name="KL628">]
Robot.bot_names      #=> ["KL628"]
Robot.reset          #=> []
c3po = Robot.new     #=> #<Robot:0x000001018ff8c0 @name="VO975">
Robot.bots           #=> [#<Robot:0x000001018ff8c0 @name="VO975">]

<强>解释

  • 解析类时,首先创建类方法reset,然后执行行reset。当self => Robot发生时,执行类方法reset,将@bots初始化为空数组。

  • 保存和修改Robot实例列表的责任在于班级。此列表保存在类实例变量@bots中。

  • Robot的实例是通过调用Robot::new创建的,initialize分配内存然后调用(私有)实例方法newRobot在哪里?由于我们没有在Robot中将其定义为类方法,因此有两种可能性:它是从Robot.ancestors => [Robot, Object, Kernel, BasicObject]的祖先(Class)中继承的,或者它是一个类Robot的实例方法,因为Robot.class => Class是一个实例的类(即Class.instance_method(:new) => #<UnboundMethod: Class#new>)让我们找出哪个:Class.instance_methods.include?(:new) => true(或Object.method(:new) => #<Method: Class#new>),Class。这两个都是!但这是有道理的,因为所有类都是Robot的实例,包括Object的超类#<Method: Class#new>Object.method(:new) new返回的Class已在Robot.method(:new).owner => Class中定义(也可以new显示。非常酷,嗯?如果你没有&#39}我已经知道了这一点,并且可以按照我在本段中所说的那样,了解了Ruby对象模型的本质!

  • 假设我们将类方法Robot添加到super,如下所示。 Object::new调用类方法Class#new(实例方法new),传递Object::new的任何参数(这里没有任何参数)。 Robot::new返回它创建的实例,def self.new super end 依次返回。因此,这种方法只是一种管道,对结果没有影响。

    Object::new
  • 我们可以对上述方法进行一些小改动,将@bots创建的实例的副本添加到数组def self.new instance = super @bots << instance instance end

    def self.new
      (@bots << super).last
    end
    
  • 我写得更紧凑一点:

    PREFACE_SIZE
  • 我已使用方法Array#samplePREFACE中的SUFFIX_SIZESUFFIX_SIZE字符中随机抽取sample个字符。 gen_name示例无需替换,因此您无法获得,例如&#34; UU112&#34;。如果您想要替换样本,请将方法def gen_name str = PREFACE_SIZE.times.with_object('') { |_,s| s << PREFACE.sample } SUFFIX_SIZE.times { str << SUFFIX.sample } str end 替换为以下内容:

    bots
  • 我创建了一个类方法@bots来返回类实例变量@bots的值。也可以通过在Robots&#39;上class << self attr_reader :name end 定义读访问器来完成此操作。单身人士课程:

    Robot.reset
  • 调用Robot时,它所包含的C的所有实例会发生什么?他们会离开森林,被拒绝和无家可归吗?在像{{1}}这样的语言中,你需要在将它们抛到一边之前释放它们的内存。在Ruby和许多其他现代语言中,这是不必要的(并且通常无法完成)。 Ruby&#34;垃圾收集&#34;跟踪所有对象,并在释放内存后终止任何其他对象不再引用的对象。很好,嗯?

答案 1 :(得分:2)

任务本身并不难,但我不喜欢你的代码组织方式。这是我在第一阶段要做的事情:

class Robot
  class Name < String
    class << self
      def sign
        "#{[*?A..?Z].sample}#{[*?A..?Z].sample}"
      end

      def number
        "#{rand 1..9}#{rand 0..9}#{rand 0..9}"
      end

      def new
        super << sign << number
      end
    end
  end
end

然后:

Robot::Name.new

构建名称列表时,很容易检查它们是否唯一。这就是我要做的事情:

class Robot
  class Names < Array
    def self.generate n
      new.tap { |array| n.times do array.add_random_name end }
    end

    def add_random_name
      name = Name.new
      include?( name ) ? add_random_name : self << name
    end
  end
end

然后:

Robot::Names.generate 7

答案 2 :(得分:1)

我知道这样做效率不高,但这样可行。

letters = [*'A'..'Z'] => 
numbers = [*100..999]
names = []
2.times{names.push(letters.shuffle.first)} => Randomizing array and choosing element
names.push(numbers.shuffle.first)
names.join => Creates a String object out of the array elements

这不太好,但它可以完成工作。

答案 3 :(得分:1)

这就是我使用y_support/name_magic

自动化Cary方法的方法
require 'y_support/all'

class Robot
  ★ NameMagic

  def name_yourself
    begin
      self.name = "#{[*?A..?Z].sample( 2 ).join}#{rand 100..999}"
    rescue NameError; retry end
  end
end

3.times { Robot.new.name_yourself }
Robot.instances #=> [PR489, NS761, OE663]
Robot.forget "PR489"
Robot.instances #=> [NS761, OE663]
Robot.forget_all_instances
Robot.instances #=> []
Robot.new.name_yourself
Robot.instances #=> [IB573]

答案 4 :(得分:0)

def save_name
  stored_names = []
  stored_names << named
end

每次创建一个名称,并通过为save_name指定一个空数组来调用stored_names删除所有以前创建的名称

修改 还有一些错误,让我先发布一个有效的解决方案:

class Robot
  attr_accessor :named , :stored_names , :rl

  def initialize()
    @stored_names = []
  end

  @@rl = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ".chars.to_a

  def name
    @named = ""
    @named << @@rl.sample
    @named << @@rl.sample
    @named << rand(100..999).to_s
    save_name 
    check_name
  end

  def save_name
    @stored_names << @named
  end

  def check_name
    @stored_names.uniq!
  end

  def reset
    @stored_names = Array.new
  end
end
  • 要访问对象的成员,您必须在其前面添加@

  • 您在save_name上拨打了check_name@named,这是一个字符串,并没有提供这些方法

  • 必须先将
  • @stored_names初始化为空数组,然后才能使用<<将元素推入其中。这通常在课程的构造函数initialize()

  • 中完成