Ruby 2.4

Set

Set 类

Parent:ObjectIncluded modules:Enumerable

Set实现无重复值的集合。这是Array的直观互操作设施和Hash快速查找的混合体。

Set可以很容易地与Enumerable对象一起使用(实现每个对象)。 大多数初始化方法和二元运算符接受除了集合和数组之外的泛型Enumerable对象。 Enumerable对象可以使用to_set方法转换为Set。

设置使用哈希作为存储,所以你必须注意以下几点:

  • 元素的等值是根据Object#eql确定的。和Object#hash。使用#compare_by_identity使一组数据按其身份进行比较。

  • Set假定每个元素的标识在存储时不会改变。修改集合中的一个元素会使集合处于不可靠状态。

  • 当要存储字符串时,将存储字符串的冻结副本,除非原始字符串已冻结。

对照

比较运算符<,>,<=和> =被实现为{proper _,} {subset?,superset?}方法的简写形式。然而,<=>操作符被故意排除,因为不是每一对集合都是可比的。({x,y}对比{x,z}))

require 'set' s1 = Set.new [1, 2] # -> #<Set: {1, 2}> s2 = [1, 2].to_set # -> #<Set: {1, 2}> s1 == s2 # -> true s1.add("foo") # -> #<Set: {1, 2, "foo"}> s1.merge([2, 6]) # -> #<Set: {1, 2, "foo", 6}> s1.subset? s2 # -> false s2.subset? s1 # -> true

公共类方法

显示来源

创建一个包含给定对象的新集合。

# File lib/set.rb, line 74 def self.[](*ary) new(ary) end

new(enum = nil) { |o| ... } Show source

创建一个包含给定枚举对象的元素的新集合。

如果给出了一个块,枚举的元素由给定的块进行预处理。

# File lib/set.rb, line 83 def initialize(enum = nil, &block) # :yields: o @hash ||= Hash.new(false) enum.nil? and return if block do_with_enum(enum) { |o| add(block[o]) } else merge(enum) end end

公共实例方法

&(enum) Show source

返回一个新集合,其中包含该集合和给定可枚举对象共有的元素。

# File lib/set.rb, line 439 def &(enum) n = self.class.new do_with_enum(enum) { |o| n.add(o) if include?(o) } n end

另外别名为: intersection

+(enum)

别名:|

-(enum) Show source

返回通过复制集合构建的新集合,删除给定可枚举对象中出现的每个元素。

# File lib/set.rb, line 432 def -(enum) dup.subtract(enum) end

还有别名:difference

<(set)

别名为:proper_subset?

<<(o)

别名为:add

<=(set)

别名为:subset?

==(other) Show source

如果两组相等,则返回true。每对元素的相等性根据Object#eql?定义。

# File lib/set.rb, line 457 def ==(other) if self.equal?(other) true elsif other.instance_of?(self.class) @hash == other.instance_variable_get(:@hash) elsif other.is_a?(Set) && self.size == other.size other.all? { |o| @hash.include?(o) } else false end end

(set)

别名为:proper_superset?

=(set)

别名为:superset?

^(enum) Show source

返回包含集合与给定枚举对象之间排他性元素的新集合。(set ^ enum)相当于((set | enum) - (set&enum))。

# File lib/set.rb, line 449 def ^(enum) n = Set.new(enum) each { |o| n.add(o) unless n.delete?(o) } n end

add(o) Show source

将给定对象添加到该集合并返回自身。 使用merge一次添加许多元素。

# File lib/set.rb, line 330 def add(o) @hash[o] = true self end

另外别名为:<<

add?(o) Show source

将给定对象添加到该集合并返回自身。如果该对象已经在该集合中,则返回nil。

# File lib/set.rb, line 338 def add?(o) add(o) unless include?(o) end

classify() { |o| ... } Show source

通过给定块的返回值对集合进行分类,并返回{value =>元素集}对的散列。对于该集合的每个元素,该块将被调用一次,并将该元素作为参数传递。

例如:

require 'set' files = Set.new(Dir.glob("*.rb")) hash = files.classify { |f| File.mtime(f).year } p hash # => {2000=>#<Set: {"a.rb", "b.rb"}>, # 2001=>#<Set: {"c.rb", "d.rb", "e.rb"}>, # 2002=>#<Set: {"f.rb"}>}

如果没有给出块,则返回一个枚举器。

# File lib/set.rb, line 493 def classify # :yields: o block_given? or return enum_for(__method__) { size } h = {} each { |i| (h[yield(i)] ||= self.class.new).add(i) } h end

clear() Show source

删除所有元素并返回自身。

# File lib/set.rb, line 162 def clear @hash.clear self end

collect!() { |o| ... } Show source

用collect()返回的元素替换元素。如果没有给出块,则返回一个枚举器。

# File lib/set.rb, line 379 def collect! block_given? or return enum_for(__method__) { size } replace(self.class.new(self) { |o| yield(o) }) end

另外别名为:map!

compare_by_identity() Show source

使集合通过他们的身份比较其元素并返回自身。Set的所有子类都可能不支持此方法。

# File lib/set.rb, line 97 def compare_by_identity if @hash.respond_to?(:compare_by_identity) @hash.compare_by_identity self else raise NotImplementedError, "#{self.class.name}\##{__method__} is not implemented" end end

compare_by_identity?() Show source

如果该集合将按其身份比较其元素,则返回true。另请参阅#compare_by_identity。

# File lib/set.rb, line 108 def compare_by_identity? @hash.respond_to?(:compare_by_identity?) && @hash.compare_by_identity? end

delete(o) Show source

从集合中删除给定的对象并返回自身。用subtract一次删除多个项目。

# File lib/set.rb, line 344 def delete(o) @hash.delete(o) self end

delete?(o) Show source

从集合中删除给定的对象并返回自身。如果该对象不在该集合中,则返回nil。

# File lib/set.rb, line 351 def delete?(o) delete(o) if include?(o) end

delete_if() { |o| ... } Show source

删除块评估为true的集合中的每个元素,并返回自身。如果没有给出块,则返回一个枚举器。

# File lib/set.rb, line 358 def delete_if block_given? or return enum_for(__method__) { size } # @hash.delete_if should be faster, but using it breaks the order # of enumeration in subclasses. select { |o| yield o }.each { |o| @hash.delete(o) } self end

difference(enum)

别名: -

disjoint?(set) Show source

如果集合和给定集合没有共同的元素,则返回true。这种方法与intersect?相反。

例如:

require 'set' Set[1, 2, 3].disjoint? Set[3, 4] # => false Set[1, 2, 3].disjoint? Set[4, 5] # => true

# File lib/set.rb, line 315 def disjoint?(set) !intersect?(set) end

divide(&func) Show source

根据给定块定义的通用性将集合划分为一组子集。

如果block的arity是2,如果block.call(o1,o2)为true,则元素o1和o2是相同的。否则,如果block.call(o1)== block.call(o2),元素o1和o2是相同的。

例如:

require 'set' numbers = Set[1, 3, 4, 6, 9, 10, 11] set = numbers.divide { |i,j| (i - j).abs == 1 } p set # => #<Set: {#<Set: {1}>, # #<Set: {11, 9, 10}>, # #<Set: {3, 4}>, # #<Set: {6}>}>

如果没有给出块,则返回一个枚举器。

# File lib/set.rb, line 523 def divide(&func) func or return enum_for(__method__) { size } if func.arity == 2 require 'tsort' class << dig = {} # :nodoc: include TSort alias tsort_each_node each_key def tsort_each_child(node, &block) fetch(node).each(&block) end end each { |u| dig[u] = a = [] each{ |v| func.call(u, v) and a << v } } set = Set.new() dig.each_strongly_connected_component { |css| set.add(self.class.new(css)) } set else Set.new(classify(&func).values) end end

each(&block) Show source

为集合中的每个元素调用一次给定的块,将元素作为参数传递。如果没有给出块,则返回一个枚举器。

# File lib/set.rb, line 322 def each(&block) block or return enum_for(__method__) { size } @hash.each_key(&block) self end

empty?() Show source

如果该集合不包含任何元素,则返回true。

# File lib/set.rb, line 157 def empty? @hash.empty? end

flatten() Show source

返回一个新集合,该集合是该集合的一个副本,递归地展平每个包含集合的集合。

# File lib/set.rb, line 216 def flatten self.class.new.flatten_merge(self) end

flatten!() Show source

等同于#flatten,但用适当的结果代替接收器。如果没有修改,返回nil。

# File lib/set.rb, line 222 def flatten! replace(flatten()) if any? { |e| e.is_a?(Set) } end

include?(o) Show source

如果集合包含给定的对象,则返回true。

请注意,包括include?member? 不要像使用其他Enumerables一样使用==测试成员相等性。

另请参阅Enumerable #include?

# File lib/set.rb, line 232 def include?(o) @hash[o] end

另外别名为:成员?

initialize_clone(orig) Show source

克隆内部哈希。

调用超类方法

# File lib/set.rb, line 130 def initialize_clone(orig) super @hash = orig.instance_variable_get(:@hash).clone end

initialize_dup(orig) Show source

Dup 内部哈希。

调用超类方法

# File lib/set.rb, line 124 def initialize_dup(orig) super @hash = orig.instance_variable_get(:@hash).dup end

inspect() Show source

返回包含该集合的人类可读表示的字符串。(“#<Set:{element1,element2,...}>”)

# File lib/set.rb, line 557 def inspect ids = (Thread.current[InspectKey] ||= []) if ids.include?(object_id) return sprintf('#<%s: {...}>', self.class.name) end ids << object_id begin return sprintf('#<%s: {%s}>', self.class, to_a.inspect[1..-2]) ensure ids.pop end end

intersect?(set) Show source

如果集合和给定集合至少有一个共同元素,则返回true。

例如:

require 'set' Set[1, 2, 3].intersect? Set[4, 5] # => false Set[1, 2, 3].intersect? Set[3, 4] # => true

# File lib/set.rb, line 297 def intersect?(set) set.is_a?(Set) or raise ArgumentError, "value must be a set" if size < set.size any? { |o| set.include?(o) } else set.any? { |o| include?(o) } end end

intersection(enum)

别名为:

keep_if() { |o| ... } Show source

删除块评估为false的集合中的每个元素,并返回自身。如果没有给出块,则返回一个枚举器。

# File lib/set.rb, line 369 def keep_if block_given? or return enum_for(__method__) { size } # @hash.keep_if should be faster, but using it breaks the order of # enumeration in subclasses. reject { |o| yield o }.each { |o| @hash.delete(o) } self end

length()

别名为:size

map!()

别名为:collect!

member?(o)

别名为:include?

merge(enum) Show source

将给定枚举对象的元素合并到集合,并返回自身。

# File lib/set.rb, line 405 def merge(enum) if enum.instance_of?(self.class) @hash.update(enum.instance_variable_get(:@hash)) else do_with_enum(enum) { |o| add(o) } end self end

proper_subset?(set) Show source

如果集合是给定集合的适当子集,则返回true。

# File lib/set.rb, line 277 def proper_subset?(set) case when set.instance_of?(self.class) @hash < set.instance_variable_get(:@hash) when set.is_a?(Set) size < set.size && all? { |o| set.include?(o) } else raise ArgumentError, "value must be a set" end end

另外别名为:<

proper_superset?(set) Show source

如果该集合是给定集合的适当超集,则返回true。

# File lib/set.rb, line 251 def proper_superset?(set) case when set.instance_of?(self.class) @hash > set.instance_variable_get(:@hash) when set.is_a?(Set) size > set.size && set.all? { |o| include?(o) } else raise ArgumentError, "value must be a set" end end

另外别名为:>

reject!(&block) Show source

等同于#delete_if,但如果没有更改,则返回nil。如果没有给出块,则返回一个枚举器。

# File lib/set.rb, line 387 def reject!(&block) block or return enum_for(__method__) { size } n = size delete_if(&block) self if size != n end

replace(enum) Show source

用给定枚举对象的内容替换集合的内容,并返回自身。

# File lib/set.rb, line 169 def replace(enum) if enum.instance_of?(self.class) @hash.replace(enum.instance_variable_get(:@hash)) self else do_with_enum(enum) # make sure enum is enumerable before calling clear clear merge(enum) end end

select!(&block) Show source

相当于#keep_if,但如果没有更改,则返回nil。如果没有给出块,则返回一个枚举器。

# File lib/set.rb, line 396 def select!(&block) block or return enum_for(__method__) { size } n = size keep_if(&block) self if size != n end

size() Show source

返回元素的数量。

# File lib/set.rb, line 151 def size @hash.size end

另外别名为:长度

subset?(set) Show source

如果集合是给定集合的子集,则返回true。

# File lib/set.rb, line 264 def subset?(set) case when set.instance_of?(self.class) @hash <= set.instance_variable_get(:@hash) when set.is_a?(Set) size <= set.size && all? { |o| set.include?(o) } else raise ArgumentError, "value must be a set" end end

另外别名为:<=

subtract(enum) Show source

删除给定可枚举对象中出现的每个元素并返回自身。

# File lib/set.rb, line 417 def subtract(enum) do_with_enum(enum) { |o| delete(o) } self end

superset?(set) Show source

如果集合是给定集合的超集,则返回true。

# File lib/set.rb, line 238 def superset?(set) case when set.instance_of?(self.class) @hash >= set.instance_variable_get(:@hash) when set.is_a?(Set) size >= set.size && set.all? { |o| include?(o) } else raise ArgumentError, "value must be a set" end end

另外别名为:> =

to_a() Show source

将集合转换为数组。元素的顺序是不确定的。

# File lib/set.rb, line 181 def to_a @hash.keys end

to_set(klass = Set, *args, &block) Show source

如果没有给出参数,则返回自身。否则,使用klass.new(self,* args,&block)将该集合转换为另一个集合。

在子类中,返回klass.new(self,* args,&block),除非被覆盖。

# File lib/set.rb, line 190 def to_set(klass = Set, *args, &block) return self if instance_of?(Set) && klass == Set && block.nil? && args.empty? klass.new(self, *args, &block) end

union(enum)

别名:|

|(enum) Show source

返回通过合并集合和给定枚举对象的元素构建的新集合。

# File lib/set.rb, line 424 def |(enum) dup.merge(enum) end

还有别名:+,union