维护 Ruby 由对象 ID 设置
Maintaining Ruby Set by object ID
我正在 Ruby 中开发具有以下属性的算法:
- 它适用于两个 Set 类型的对象,其中每个元素都是一个数组,其中所有元素都是 String 类型
- 所涉及的每个数组元素个数相同
- 没有两个数组碰巧具有相同的内容(与
==
比较时)
- 该算法涉及将数组从一个 Set 移动到另一个(或返回)、存储对某些数组的引用以及测试该引用是否是数组的一部分的许多操作
- 数组没有重复;所有数组始终保持其对象 ID。
本机实现会做这样的事情(给你想法);实际上,这里的数组有更长的字符串和更多的元素:
# 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
我正在 Ruby 中开发具有以下属性的算法:
- 它适用于两个 Set 类型的对象,其中每个元素都是一个数组,其中所有元素都是 String 类型
- 所涉及的每个数组元素个数相同
- 没有两个数组碰巧具有相同的内容(与
==
比较时) - 该算法涉及将数组从一个 Set 移动到另一个(或返回)、存储对某些数组的引用以及测试该引用是否是数组的一部分的许多操作
- 数组没有重复;所有数组始终保持其对象 ID。
本机实现会做这样的事情(给你想法);实际上,这里的数组有更长的字符串和更多的元素:
# 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