如何正确编写ruby方法

时间:2017-02-24 16:18:39

标签: ruby

我正在尝试红宝石。我想创建一个可以继续序列的程序。

  

1

     

11

     

21

     

1211

     

111221

(下一行计算前一行的每个数字) 例如,最后一行是(见上一个)1中的一个,2个中的一个,以及1中的两个。 我制作了一个代码并且工作正常:

5.times do
result_seq = []
count = 1
puts initial_seq.join
initial_seq.size.times do
  if (value = initial_seq.shift) == initial_seq.first
    count += 1
  else
    result_seq << count << value
    count = 1
  end
end
initial_seq = result_seq
end

但现在我想写一个名为 Next

的简单方法

我想:

sec = Sequence.new(1)
sec.next -> will return 11
sec.next.next -> will return 21
sec.next.next.next -> will return 1211

如何使用我的代码正确编写?

UPD

我为它编写了测试:

require "spec_helper"

require "sequence"

describe Sequence do
  let(:sequence) { Sequence.new("1") }

  describe "to_s" do
    it "return initial value" do
      expect(sequence.to_s).to eql "1"
    end
  end

  describe "next" do
    it "generate next state" do
      expect(sequence.next.to_s).to eql "11"
    end

    it "return Sequence instance" do
      expect(sequence.next).to be_an_instance_of(Sequence)
    end

    it "generate next state 2 times" do
      expect(sequence.next.next.to_s).to eql "21"
    end

    it "generate next state 3 times" do
      expect(sequence.next.next.next.to_s).to eql "1211"
    end
  end
end

2 个答案:

答案 0 :(得分:2)

class Sequence
  attr_reader :initial_seq

  def initialize(initial_seq = [])
    @initial_seq = initial_seq
    print_next
  end

  def print_next
    result_seq = []
    count = 1
    puts initial_seq.join
    initial_seq.size.times do
      if (value = initial_seq.shift) == initial_seq.first
        count += 1
      else
        result_seq << count << value
        count = 1
      end
    end
    @initial_seq = result_seq
    self #<===== The most important part for being able to chain `print_next`
  end
end

用法:

Sequence.new([1]).print_next.print_next.print_next.print_next
1
11
21
1211
111221

修改

如果要使用整数参数初始化它,而不是数组:

def initialize(number)
  @initial_seq = [number]
  print_next
end

Sequence.new(1).print_next.print_next
1
11
21

或者,如果您不希望initialize接受参数(假设它始终以1开头):

def initialize
  @initial_seq = [1]
  print_next
end


Sequence.new.print_next.print_next
1
11
21

答案 1 :(得分:2)

Ruby提供了枚举器,其行为与OP类似。让原始代码几乎不变:

seq = Enumerator.new do |yielder|
  initial_seq = [1]

  loop do  #endless loop, but don't worry, its lazy
    result_seq = []
    count = 1
    yielder << initial_seq.join
    initial_seq.size.times do
      if (value = initial_seq.shift) == initial_seq.first
        count += 1
      else
        result_seq << count << value
        count = 1
      end
    end
    initial_seq = result_seq
  end
end

5.times{puts seq.next}
puts seq.next