2

我开始在 Test-First 上解决一些示例问题,并制定了一个使用 Ruby 1.8.7 通过所有 RSpec 测试的解决方案。我刚刚升级了我的操作系统,Ruby 也升级了;我的代码不再通过 RSpec 测试。谁能帮我理解为什么这不再起作用了?

我的代码

  def entries 
    @d
  end

错误信息

失败:

1)字典可以添加带有关键字和定义的整个条目

Failure/Error: @d.entries.should == {'fish' => 'aquatic animal'}
   expected: {"fish"=>"aquatic animal"}
        got: {["fish"]=>["aquatic animal"]} (using ==)

差异:

 @@ -1,2 +1,2 @@
   -"fish" => "aquatic animal"
   +["fish"] => ["aquatic animal"]

#

我不知道要对格式进行什么更改。(其中一个 RSpec 测试是 @d 在创建时必须为空,所以当我尝试通过显式格式化来修改 @d 时它也会失败,但我想这里有一个简单的类型问题我不是理解。)

更新:更多代码

class Dictionary
  def initialize d = {}
    @d = d
  end

  def entries
    @d
  end

  def keywords
    @d.keys.sort
  end

  def add words
    n_key = words.keys
    n_val = words.values
    @d[n_key] = n_val
  end
end
4

1 回答 1

1

看起来您正在尝试通过一次添加几个单词来进行某种批量分配,但这不是这样做的方法。

Ruby Hash 可以有任何东西作为键,这包括事物的数组。它不像 JavaScript,它会自动转换为字符串,或者其他具有相同类型转换为特定字典键类型的语言。在 Ruby 中,任何对象都可以。

所以你的添加词方法应该是:

def add words
  words.each do |word, value|
    @d[word] = value
  end
end

作为注释,使用名称 like@d是非常糟糕的形式。尝试更具体地说明那是什么,否则您可能会无休止地混淆人们。充满诸如@d,x之类的程序的程序S很难调试和维护。如果有点冗长而不是简洁和模棱两可,最好是清楚。

其次,尚不清楚您的Dictionary班级与自身有何不同Hash。也许您可以将其设为子类并为自己省点麻烦。例如:

class Dictionary < Hash
  def keywords
    keys.sort
  end

  def add words
    merge!(words)
  end
end

一般来说,最好使用核心 Ruby 类来做你想做的事,然后从那里开始构建。重新发明轮子会导致不兼容和沮丧。内置的 Hash 类有一大堆实用方法,这些方法对于进行数据转换、转换和迭代非常方便,因为创建自己的不透明包装类会丢失这些东西。

merge!方法特别将数据添加到现有哈希中,这正是您想要的。

于 2014-04-08T04:20:37.780 回答