Ruby 中的集合 - 是否有集合 class 类似于 Set 但具有 Hash 的成员访问权限?
Collections in Ruby - is there a collections class like Set but with the member access of Hash?
在阅读了彼得·琼斯的书 Effective Ruby 中的 Collections 章节后,集合 class似乎提供了一种有趣的 Hash 替代方法。关于集合 class,琼斯说:
It’s a lot like its mathematical cousin, a collection of unordered unique elements with operations such as union, intersection, and subset/superset testing.
我唯一担心的是 Set class 是否可能不提供对实际成员对象的直接访问。
目前,我正在尝试使用 Set
(或 Set
之类的东西)来实现天真的 OptionSet
API,这样 OptionSet
可能是 Option
或 ValueOption
类型,后者是 Option
的子 class。 API 可能需要访问存储在每个 OptionSet
各自集合中的对象——无论是存储在单独的哈希、数组、其他容器对象中,还是通过某些方法存储在 OptionSet
中继承的实现,例如 Set
作为 superclass.
我想在 OptionSet
中使用 Set
,或者只是将 OptionSet
实现为 Set
的子 class。但是,如果 Set
可能不提供对成员对象的直接访问,一旦存储 - 没有遍历 Set
中的每个成员对象,直到找到任何表面上的匹配(例如一旦找到任何 Option
或集合中的 ValueOption
,这样“匹配项”就有一个等效的 Option.name
,通常是一个符号)——也许有更有效的替代方法?
我会提供示例代码,但 OptionSet
的实现目前不可用。在伪代码中,我试图将 OptionSet#getopt(name)
实现为 return 存储在 OptionSet
中的任何命名 Option
对象的值,如果没有存储此类选项,则为 false。
#getopt
方法将调用 self.getoptObj(name)
,这是一种受保护的方法,需要访问集合中命名选项的实际 Option
对象。除了那部分实现,否则Set可能直接适合。
在任何类似于 Scheme 的语言中,Ruby 标准库可能不提供 AssociativeList class, 本身 ?简单地说,我想知道是否有像 Set
这样的 class —— 即使用 Set
中的集合论方法 —— 但具有 Hash
?[=46 的成员访问权限=]
更新
我已经尝试实现 MappedSet
class,至少在伪代码中,例如使用实例 Hash
值来存储通用“键”和成员对象。但是,我认为这对于 Set
的国际存储来说是多余的。也许我应该简单地扩展 Hash
.
如果你想创建一个像 class 这样的散列,你可以使用 DelegateClass:
class FalsyHash < DelegateClass(Hash)
def initialize(hash)
super.tap { |result| result.default = false }
end
end
irb(main):001:0> f = FalsyHash.new(a: :b)
=> {:a=>:b}
irb(main):002:0> f[:b]
=> false
irb(main):003:0> f.is_a?(Hash)
=> false
这基本上只是一个 class,它采用所提供的 class 的一个实例并将其包装起来,以便转发方法调用。由于它实际上不是哈希的实例,因此我们避免了核心方法检查我们是否正在处理哈希时发生的陷阱,如果我们使用哈希的子 class 就会发生这种情况。
Delegator、SimpleDelegator 和 Forwardable 可以实现相同的目的 - DelegateClass 只是一种直接的包装方式 classes。
您还可以通过使用模块扩展 Hash 的特定实例来扩充它们:
module Reversable
def reverse
transform_values { |v| v.respond_to?(:reverse) ? v.reverse : v }
end
end
# Guess what this returns for a cookie
{ foo: 'olleH', bar: nil, baz: 'dlrow' }.extend(Reversable)
.reverse
.values
.compact
.sort
.join(" ")
在阅读了彼得·琼斯的书 Effective Ruby 中的 Collections 章节后,集合 class似乎提供了一种有趣的 Hash 替代方法。关于集合 class,琼斯说:
It’s a lot like its mathematical cousin, a collection of unordered unique elements with operations such as union, intersection, and subset/superset testing.
我唯一担心的是 Set class 是否可能不提供对实际成员对象的直接访问。
目前,我正在尝试使用 Set
(或 Set
之类的东西)来实现天真的 OptionSet
API,这样 OptionSet
可能是 Option
或 ValueOption
类型,后者是 Option
的子 class。 API 可能需要访问存储在每个 OptionSet
各自集合中的对象——无论是存储在单独的哈希、数组、其他容器对象中,还是通过某些方法存储在 OptionSet
中继承的实现,例如 Set
作为 superclass.
我想在 OptionSet
中使用 Set
,或者只是将 OptionSet
实现为 Set
的子 class。但是,如果 Set
可能不提供对成员对象的直接访问,一旦存储 - 没有遍历 Set
中的每个成员对象,直到找到任何表面上的匹配(例如一旦找到任何 Option
或集合中的 ValueOption
,这样“匹配项”就有一个等效的 Option.name
,通常是一个符号)——也许有更有效的替代方法?
我会提供示例代码,但 OptionSet
的实现目前不可用。在伪代码中,我试图将 OptionSet#getopt(name)
实现为 return 存储在 OptionSet
中的任何命名 Option
对象的值,如果没有存储此类选项,则为 false。
#getopt
方法将调用 self.getoptObj(name)
,这是一种受保护的方法,需要访问集合中命名选项的实际 Option
对象。除了那部分实现,否则Set可能直接适合。
在任何类似于 Scheme 的语言中,Ruby 标准库可能不提供 AssociativeList class, 本身 ?简单地说,我想知道是否有像 Set
这样的 class —— 即使用 Set
中的集合论方法 —— 但具有 Hash
?[=46 的成员访问权限=]
更新
我已经尝试实现 MappedSet
class,至少在伪代码中,例如使用实例 Hash
值来存储通用“键”和成员对象。但是,我认为这对于 Set
的国际存储来说是多余的。也许我应该简单地扩展 Hash
.
如果你想创建一个像 class 这样的散列,你可以使用 DelegateClass:
class FalsyHash < DelegateClass(Hash)
def initialize(hash)
super.tap { |result| result.default = false }
end
end
irb(main):001:0> f = FalsyHash.new(a: :b)
=> {:a=>:b}
irb(main):002:0> f[:b]
=> false
irb(main):003:0> f.is_a?(Hash)
=> false
这基本上只是一个 class,它采用所提供的 class 的一个实例并将其包装起来,以便转发方法调用。由于它实际上不是哈希的实例,因此我们避免了核心方法检查我们是否正在处理哈希时发生的陷阱,如果我们使用哈希的子 class 就会发生这种情况。
Delegator、SimpleDelegator 和 Forwardable 可以实现相同的目的 - DelegateClass 只是一种直接的包装方式 classes。
您还可以通过使用模块扩展 Hash 的特定实例来扩充它们:
module Reversable
def reverse
transform_values { |v| v.respond_to?(:reverse) ? v.reverse : v }
end
end
# Guess what this returns for a cookie
{ foo: 'olleH', bar: nil, baz: 'dlrow' }.extend(Reversable)
.reverse
.values
.compact
.sort
.join(" ")