0

そこで、Ruby でディクショナリ オブジェクトを作成し、プロジェクトの一部として多数の RSPEC テストに合格させようとしています。これまでのところは順調ですが、1 つの特定のテストで行き詰まっています。そのテストまでのRSPECは次のとおりです。

require 'dictionary'

describe Dictionary do
  before do
    @d = Dictionary.new
  end

  it 'is empty when created' do
    @d.entries.should == {}
  end

  it 'can add whole entries with keyword and definition' do
    @d.add('fish' => 'aquatic animal')
    @d.entries.should == {'fish' => 'aquatic animal'}
    @d.keywords.should == ['fish']
  end

  it 'add keywords (without definition)' do
    @d.add('fish')
    @d.entries.should == {'fish' => nil}
    @d.keywords.should == ['fish']
  end

  it 'can check whether a given keyword exists' do
    @d.include?('fish').should be_false
  end

  it "doesn't cheat when checking whether a given keyword exists" do
    @d.include?('fish').should be_false # if the method is empty, this test passes with nil returned
    @d.add('fish')
    @d.include?('fish').should be_true # confirms that it actually checks
    @d.include?('bird').should be_false # confirms not always returning true after add
  end
end

最後のテスト「特定のキーワードが存在するかどうかを確認するときにチートしない」以外は、これまでのところすべて合格しています。どうすればそれを通過させることができるかについて頭を悩ませようとしていますが、これまでのところ成功していません。どんな助けでも大歓迎です。これが私がこれまでに持っているものです:

class Dictionary
  attr_accessor :keywords, :entries
  def initialize 
    @entries = {}
     end
 def add(defs)
    defs.each do |word, definition|
      @entries[word] = definition
    end
  end
  def keywords
    input = []
    @entries.each do |key, value|
    input << key
    end
    input.sort  
  end
  def  include?(key)
    self.keywords.include?(keywords.to_s) 
  end
end

前もって感謝します!

4

3 に答える 3

3

バグがあります:

self.keywords.include?(keywords.to_s) 

keywords配列を返します。keywords.to_sのパラメーターとして使用することはできずkeywords.include?、一致することを期待することはできません。

irb(メイン):002:0> キーワード = %w[abc]
=> ["a", "b", "c"]
irb(メイン):003:0> キーワード.to_s
=> "[\"a\", \"b\", \"c\"]"
irb(メイン):004:0> キーワード.インクルード?(キーワード.to_s)
=>偽
irb(メイン):005:0> キーワード.include?('a')
=>真

keywords配列を見つけたい場合は、配列内の個々の要素を使用する必要があるためです。keywords.to_sは、配列の文字列化されたバージョンであることに注意してください'["a", "b", "c"]'。次に問題が発生したときに問題を認識するのに役立つことを願っています。

ドキュメントからinclude?

  = [「a」、「b」、「c」]
  a.include?("b") #=> true
  a.include?("z") #=> false

したがって、次のように変更します。

  def include?(キー)
    self.keywords.include?(keywords.to_s)
  終わり

に:

  def include?(キー)
    self.keywords.include?(キー)
  終わり

「騙されない」とは?どのようにコードをチートできますか? それはあなたが言ったことをするだけです。以前のすべてのテストは、「チートしない」ブロックでテストされている条件を除外しているように見えます。

@d.include?('bird').should be_false # confirms not always returning true after add

それに含める価値があります。あなたが使用することができます:

@d.add('fish')
@d.include?('bird').should be_false # confirms not always returning true after add

コードがどのように機能するか本当にわからない場合。

リストがkeywords大きくなるほど遅くなり、呼び出すたびに実行が遅くなる配列を使用して構築する代わりに、すでにハッシュであるという事実を利用して、そのメソッドを使用します。@entriesinclude?@entries

def keywords
  @entries.keys.sort
end

def include?(key)
  !!@entries[key]
end

または、これを次のように使用しますinclude?

def include?(キー)
  @entries.key?(キー)
終わり
于 2013-03-05T17:02:51.327 に答える
1

コメントでtotallymikeが言及しているように、必要な機能のほとんどは既にHash. 必要なわずかに異なるインターフェイスについては、継承する必要がありますHash

class Dictionary < Hash
  def add(defs)
    defs = {defs => nil} unless defs.kind_of?(Hash)
    merge!(defs)
  end
  alias entries dup
  def keywords; keys.sort end
end
于 2013-03-05T16:58:42.033 に答える
0

これは、「特定のキーワードが存在するかどうかを確認するときに不正行為をしない」方法を理解するのに役立ちますか?

@h = Hash.new{|h,k,v| h[k] = nil}
@h["fish"]
p @h #=> {"fish"=>nil}

この部分は、ハッシュに{|h,k,v| h[k] = nil}キーが存在しない場合に実行されます。キーを追加し、値を nil にします。

于 2013-06-12T19:07:04.477 に答える