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