维护 Ruby 由对象 ID 设置

Maintaining Ruby Set by object ID

我正在 Ruby 中开发具有以下属性的算法:

本机实现会做这样的事情(给你想法);实际上,这里的数组有更长的字符串和更多的元素:

 # Set up all Arrays involved
 master=[
   %w(a b c d), 
   %w(a b c x),
   %w(u v w y),
   # .... and so on
 ]
 # Create initial sets.
 x=Set.new
 y=Set.new
 # ....
 x.add(master[0])
 x.add(master[2])
 y.add(master[1])
 # ....
 # Operating on the sets.
 i=1
 # ...
 arr=master[i]
 # Move element arr from y to x, if it is in y
 if(y.member?(arr)
   y.delete(arr)
   x.add(arr)
 end
 # Do something with the sets
 x.each { |arr| puts arr.pretty_print }

这确实可行,只是因为数组的内容各不相同。但是,成员资格测试意味着 y.member?(arr) 测试我们的 Set 中没有一个具有与 arr 相同数组内容的对象,而验证我们没有进行测试就足够了我们的集合中已经没有一个具有相同 object_id 的元素,所以我担心性能。根据我的理解,找到一个对象的对象 ID 很便宜,而且因为它只是一个数字,所以维护一组数字比维护一组字符串数组更高效。

因此我可以尝试将我的两个集合定义为 object_id 的集合,并且成员资格测试会更快。然而,当迭代一个集合时,使用 object_id 来查找数组本身是昂贵的(我将不得不搜索 ObjectSpace)。

另一种可能性是不维护数组集,而是维护主数组中的索引集。例如,我的代码将是

x.add(0) # instead of x.add(master[0])

并且迭代一个 Set 就是,即

x.each { |i| puts master[i].pretty_print }

我想知道是否有更好的方法 - 例如,我们可以以某种方式“教导”Set.new 使用对象标识来维护其成员,而不是相等。

我认为您正在寻找 Set#compare_by_identity,这使得集合使用其内容的对象标识(即对象 ID)。

x = Set.new
x.compare_by_identity