2013-03-05 62 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}部分时的一个关键是存在于哈希运行。它添加密钥并给它一个零值。