4

我们在 Ruby 1.8.7 中做了一些工作,需要遍历和分区一个无向图,这在生产中已经奇怪地失败了。当我将失败的代码提取到最简单的组件时,我得到了这个奇怪的失败测试:

it 'should be able to clear a ruby set of arrays' do
  a = ["2", "b", "d"]
  b = ["1", "a", "c", "e", "f"]
  set = Set.new([a, b])
  a.concat(b)

  p "before clear: #{set.inspect}"
  set.clear
  p "after clear: #{set.inspect}"
  set.size.should == 0
end

测试失败,输出如下:

"before clear: #<Set: {[\"1\", \"a\", \"c\", \"e\", \"f\"], [\"2\", \"b\", \"d\", \"1\", \"a\", \"c\", \"e\", \"f\"]}>"
"after clear: #<Set: {[\"2\", \"b\", \"d\", \"1\", \"a\", \"c\", \"e\", \"f\"]}>"

expected: 0
     got: 1 (using ==)

从集合中删除的尝试也以奇怪的方式表现。我猜 Ruby 在 concat() 下更改的数组中键的哈希值被挂断了,但我当然应该仍然能够清除 Set。正确的?

4

2 回答 2

1

有一个解决方法,如果您在修改密钥后复制集合,新集合将具有更新的密钥并正确清除。所以设置set = set.dup将解决这个问题。

于 2012-06-12T18:37:58.853 回答
1

.dup 方法确实是我的第一个解决方法,并且按照宣传的方式进行。

我最终将以下猴子补丁添加到 Set:

class Set
  def rehash
    @hash.rehash
  end
end

这允许我在更改其哈希值的任何操作后重新哈希集合的键。

这似乎都在 Ruby 1.9 中得到修复。

于 2012-06-13T00:47:49.880 回答