2013-03-05 67 views
0

所以我試圖在Ruby中創建一個字典對象,並讓它通過一堆RSPEC測試作爲項目的一部分。到目前爲止它一直很好,但是我被困在一個特定的測試中。這裏的RSPEC,直到該測試:Ruby中的字典對象

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 

在此先感謝!

+2

「在檢查給定關鍵字是否存在時不作弊」中的哪一個失敗? – sawa 2013-03-05 16:52:21

+5

原諒我,如果這是粗魯的,但我可以問這個對象的重點是什麼?我沒有看到任何不是由哈希提供的功能.. – 2013-03-05 16:52:26

+3

你忽略提及它如何失敗。 – 2013-03-05 16:54:00

回答

3

有一個錯誤:

self.keywords.include?(keywords.to_s) 

keywords返回數組。不能使用keywords.to_s作爲keywords.include?參數,並期望它找到一個匹配:

 
irb(main):002:0> keywords = %w[a b c] 
=> ["a", "b", "c"] 
irb(main):003:0> keywords.to_s 
=> "[\"a\", \"b\", \"c\"]" 
irb(main):004:0> keywords.include?(keywords.to_s) 
=> false 
irb(main):005:0> keywords.include?('a') 
=> true 

,因爲你需要的,如果你想找到它的keywords陣列中使用一個單獨的元素。請注意,keywords.to_s是數組的字符串版本,也可能是:'["a", "b", "c"]'。希望這可以幫助您在下次遇到問題時識別出問題。

the documentationinclude?

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

所以,變化:

 
    def include?(key) 
    self.keywords.include?(keywords.to_s) 
    end 

到:

 
    def include?(key) 
    self.keywords.include?(key) 
    end 

你說的 「不作弊」 呢?代碼如何作弊?它只是做你說的。所有先前的測試看起來像他們會排除在「不作弊」塊中進行測試的條件,其僅僅使得:

@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,這將變慢較大的@entries名單,並導致include?運行速度較慢你怎麼稱呼它任何時候, 利用的事實,@entries已經是一個哈希並使用其方法:

def keywords 
    @entries.keys.sort 
end 

def include?(key) 
    [email protected][key] 
end 

或者用這個include?

 
def include?(key) 
    @entries.key?(key) 
end 
+0

謝謝你的幫助,我真的很感激。 – PaperKraftMike 2013-03-06 15:54:53

1

正如評論中提到的那樣,大多數你想要的功能已經存在於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 
+0

@Joshua您添加了'entries',這在使用子類的實現下是無用的。而你錯誤地將'關鍵字'的定義替換爲不'排序'的定義。 – sawa 2013-03-05 17:05:39

+0

它需要通過規範的條目,並且規範中沒有關於要排序的鍵。 – 2013-03-06 15:32:29

+2

@sawa,哇謝謝。這個答案真的讓我以一種全新的方式思考Ruby中現有的類。謝謝! – PaperKraftMike 2013-03-06 15:37:29

0

這是否給你一個想法如何去傳遞「d在檢查給定關鍵字是否存在時不作弊「?

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

{|h,k,v| h[k] = nil}部分時的一個關鍵是存在於哈希運行。它添加密鑰並給它一個零值。