这是Ruby中一组数组的预期行为吗?

时间:2012-06-12 07:43:32

标签: ruby set concat

我们在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。正确?

2 个答案:

答案 0 :(得分:1)

有一种解决方法,如果您在修改密钥后复制了该集,则新集将具有更新的密钥并正确清除。因此,设置set = set.dup将解决该问题。

答案 1 :(得分:1)

.dup方法确实是我的第一个解决方法,并按照广告宣传。

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

class Set
  def rehash
    @hash.rehash
  end
end

允许我在更改其哈希值的任何操作之后重新发送集合的密钥。

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