class Set
Set 类实现了一个不包含重复元素的无序集合。它融合了 Array 直观的互操作性和 Hash 快速查找的优点。
Set 易于与 Enumerable 对象(实现 each)配合使用。大多数初始化方法和二元运算符除了接受 Set 和 Array 外,还可以接受通用的 Enumerable 对象。可以使用 to_set 方法将 Enumerable 对象转换为 Set。
Set 在内部使用类似于 Hash 的数据结构进行存储,但它只存储键而没有值。
-
元素的相等性由
Object#eql?和Object#hash决定。可以使用Set#compare_by_identity使 Set 仅通过对象的身份来比较元素。 -
Set 假定每个元素的身份在其存储期间不会改变。修改 Set 中的元素会导致 Set 处于不可靠的状态。
-
当字符串要被存储时,除非原始字符串已经是冻结状态,否则会存储该字符串的冻结副本。
比较
比较运算符 <、>、<= 和 >= 是 {proper_,}{subset?,superset?} 方法的简写。<=> 运算符反映了这种顺序,或者对于同时包含不同元素的 Set(例如 {x, y} vs. {x, z})返回 nil。
示例
s1 = Set[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
联系方式
-
Akinori MUSHA <knu@iDaemons.org> (当前维护者)
继承 Set
在 Ruby 4.0(发布于 2025 年 12 月)之前,Set 有一个不同的、效率较低的实现。它被重写为 C 语言,并且一些核心方法的行为也进行了调整。
为了保持向后兼容性,当一个类继承自 Set 时,会额外包含 Set::SubclassCompatible 模块,这使得继承类的行为以及内部方法名称更接近 Ruby 4.0 之前的状态。
例如,这在 inspect 方法的行为中很容易看出。
p Set[1, 2, 3] # prints "Set[1, 2, 3]" class MySet < Set end p MySet[1, 2, 3] # prints "#<MySet: {1, 2, 3}>", like it was in Ruby 3.4
对于新代码,如果不需要向后兼容性,建议继承 Set::CoreSet,它避免了包含“兼容性”层。
class MyCoreSet < Set::CoreSet end p MyCoreSet[1, 2, 3] # prints "MyCoreSet[1, 2, 3]"
Set 的方法
首先,其他地方的方法。类 Set
-
继承自 Object 类。
-
包含 Enumerable 模块,该模块提供了数十种额外的方法。
特别是,类 Set 本身并没有很多用于获取或迭代的方法。相反,它依赖于 Enumerable 中的方法。
这里,类 Set 提供了对以下方面有用的方法:
创建 Set 的方法
Set 操作的方法
-
|(别名为union和+): 返回一个包含self中所有元素和给定 Enumerable 对象中所有元素的新 Set(无重复)。 -
&(别名为intersection): 返回一个包含self和给定 Enumerable 对象中共有的所有元素的新 Set。 -
-(别名为difference): 返回self的一个副本,其中移除了给定 Enumerable 对象中的所有元素。 -
^: 返回一个新 Set,其中包含self和给定 Enumerable 对象中的所有元素,但不包含两者共有的元素。
比较方法
-
<=>: 返回 -1、0 或 1,表示self小于、等于或大于给定对象。 -
==: 根据Object#eql?判断,返回self和给定 Enumerable 对象是否相等。 -
compare_by_identity?: 返回 Set 是否仅通过身份来比较元素。
查询方法
-
empty?: 返回 Set 是否为空。 -
proper_subset?(别名为 <): 返回给定 Enumerable 对象是否为 Set 的真子集。 -
proper_superset?(别名为 >): 返回给定 Enumerable 对象是否为 Set 的真超集。 -
disjoint?: 如果 Set 和给定的 Enumerable 对象没有任何共同元素,则返回true,否则返回false。 -
intersect?: 如果 Set 和给定的 Enumerable 对象有任何共同元素,则返回true,否则返回false。 -
compare_by_identity?: 返回 Set 是否仅通过身份来比较元素。
赋值方法
-
add?: 如果给定对象不在 Set 中,则将其添加并返回self;否则,返回nil。 -
merge: 将每个给定 Enumerable 对象中的元素合并到 Set 中,并返回self。 -
replace: 用给定 Enumerable 对象的内容替换 Set 的内容。
删除方法
-
clear: 移除 Set 中的所有元素;返回self。 -
delete: 从 Set 中移除给定对象;返回self。 -
delete?: 如果给定对象在 Set 中,则将其移除并返回self;否则,返回nil。 -
subtract: 从 Set 中移除每个给定对象;返回self。 -
delete_if- 根据给定块指定的条件移除元素。 -
keep_if: 根据给定块指定的条件移除不满足条件的元素。 -
reject!根据给定块指定的条件移除元素。
转换方法
-
classify: 根据给定块确定元素的分类,并返回一个哈希表。 -
divide: 根据给定块确定元素的分类,并返回一个哈希表;与classify不同之处在于块可以接受一个或两个参数。 -
flatten: 返回一个递归展平后的新 Set。 -
flatten!: 将self中的每个嵌套 Set 替换为该 Set 中的元素。 -
join: 返回一个字符串,其中包含 Set 中的所有元素,必要时转换为字符串,并由指定的记录分隔符连接。 -
to_a: 返回一个包含 Set 中所有元素的数组。 -
to_set: 如果没有参数和块,则返回self;如果给定了块,则返回由块返回值构成的新 Set。
迭代方法
-
each: 使用每个连续的元素调用块;返回self。
其他方法
-
reset: 重置内部状态;如果 Set 中的元素被修改,则很有用。
Public Class Methods
Source
static VALUE
set_s_create(int argc, VALUE *argv, VALUE klass)
{
VALUE set = set_alloc_with_size(klass, argc);
set_table *table = RSET_TABLE(set);
int i;
for (i=0; i < argc; i++) {
set_table_insert_wb(table, set, argv[i], NULL);
}
return set;
}
返回一个新的 Set 对象,其中填充了给定的对象。参见 Set::new。
Source
# File ext/json/lib/json/add/set.rb, line 9 def self.json_create(object) new object['a'] end
参见 as_json。
Source
static VALUE
set_i_initialize(int argc, VALUE *argv, VALUE set)
{
if (RBASIC(set)->flags & RSET_INITIALIZED) {
rb_raise(rb_eRuntimeError, "cannot reinitialize set");
}
RBASIC(set)->flags |= RSET_INITIALIZED;
VALUE other;
rb_check_arity(argc, 0, 1);
if (argc > 0 && (other = argv[0]) != Qnil) {
if (RB_TYPE_P(other, T_ARRAY)) {
long i;
int block_given = rb_block_given_p();
set_table *into = RSET_TABLE(set);
for (i=0; i<RARRAY_LEN(other); i++) {
VALUE key = RARRAY_AREF(other, i);
if (block_given) key = rb_yield(key);
set_table_insert_wb(into, set, key, NULL);
}
}
else {
rb_block_call(other, enum_method_id(other), 0, 0,
rb_block_given_p() ? set_initialize_with_block : set_initialize_without_block,
set);
}
}
return set;
}
创建包含给定 enumerable 对象中元素的新 Set。
如果给定了块,则 enumerable 中的元素将由给定的块进行预处理。
Set.new([1, 2]) #=> Set[1, 2] Set.new([1, 2, 1]) #=> Set[1, 2] Set.new([1, 'c', :s]) #=> Set[1, "c", :s] Set.new(1..5) #=> Set[1, 2, 3, 4, 5] Set.new([1, 2, 3]) { |x| x * x } #=> Set[1, 4, 9]
Public Instance Methods
Source
static VALUE
set_i_intersection(VALUE set, VALUE other)
{
VALUE new_set = set_s_alloc(rb_obj_class(set));
set_table *stable = RSET_TABLE(set);
set_table *ntable = RSET_TABLE(new_set);
if (rb_obj_is_kind_of(other, rb_cSet)) {
set_table *otable = RSET_TABLE(other);
if (set_table_size(stable) >= set_table_size(otable)) {
/* Swap so we iterate over the smaller set */
otable = stable;
set = other;
}
struct set_intersection_data data = {
.set = new_set,
.into = ntable,
.other = otable
};
set_iter(set, set_intersection_i, (st_data_t)&data);
}
else {
struct set_intersection_data data = {
.set = new_set,
.into = ntable,
.other = stable
};
rb_block_call(other, enum_method_id(other), 0, 0, set_intersection_block, (VALUE)&data);
}
return new_set;
}
返回一个新 Set,其中包含 Set 和给定 enumerable 对象中的共有元素。
Set[1, 3, 5] & Set[3, 2, 1] #=> Set[3, 1] Set['a', 'b', 'z'] & ['a', 'b', 'c'] #=> Set["a", "b"]
Source
static VALUE
set_i_difference(VALUE set, VALUE other)
{
return set_i_subtract(rb_obj_dup(set), other);
}
返回一个复制 Set 的新 Set,并移除在给定 enumerable 对象中出现的所有元素。
Set[1, 3, 5] - Set[1, 5] #=> Set[3] Set['a', 'b', 'z'] - ['a', 'c'] #=> Set["b", "z"]
Source
static VALUE
set_i_compare(VALUE set, VALUE other)
{
if (rb_obj_is_kind_of(other, rb_cSet)) {
size_t set_size = RSET_SIZE(set);
size_t other_size = RSET_SIZE(other);
if (set_size < other_size) {
if (set_le(set, other) == Qtrue) {
return INT2NUM(-1);
}
}
else if (set_size > other_size) {
if (set_le(other, set) == Qtrue) {
return INT2NUM(1);
}
}
else if (set_le(set, other) == Qtrue) {
return INT2NUM(0);
}
}
return Qnil;
}
当 Set 相同时返回 0,当 Set 是给定 Set 的真子集/超集时返回 -1/1,或者当它们都有唯一元素时返回 nil。
Source
static VALUE
set_i_eq(VALUE set, VALUE other)
{
if (!rb_obj_is_kind_of(other, rb_cSet)) return Qfalse;
if (set == other) return Qtrue;
set_table *stable = RSET_TABLE(set);
set_table *otable = RSET_TABLE(other);
size_t ssize = set_table_size(stable);
size_t osize = set_table_size(otable);
if (ssize != osize) return Qfalse;
if (ssize == 0 && osize == 0) return Qtrue;
if (stable->type != otable->type) return Qfalse;
struct set_equal_data data;
data.set = other;
return rb_exec_recursive_paired(set_recursive_eql, set, other, (VALUE)&data);
}
当两个 Set 相同时返回 true。
Source
static VALUE
set_i_xor(VALUE set, VALUE other)
{
VALUE new_set = rb_obj_dup(set);
if (rb_obj_is_kind_of(other, rb_cSet)) {
set_iter(other, set_xor_i, (st_data_t)new_set);
}
else {
VALUE tmp = set_s_alloc(rb_cSet);
set_merge_enum_into(tmp, other);
set_iter(tmp, set_xor_i, (st_data_t)new_set);
}
return new_set;
}
返回一个新 Set,其中包含 Set 和给定 enumerable 对象之间的独占元素。(set ^ enum) 等同于 ((set | enum) - (set & enum))。
Set[1, 2] ^ Set[2, 3] #=> Set[3, 1] Set[1, 'b', 'c'] ^ ['b', 'd'] #=> Set["d", 1, "c"]
Source
static VALUE
set_i_union(VALUE set, VALUE other)
{
set = rb_obj_dup(set);
set_merge_enum_into(set, other);
return set;
}
返回一个新 Set,它是通过合并 Set 和给定 enumerable 对象中的元素而构建的。
Set[1, 2, 3] | Set[2, 4, 5] #=> Set[1, 2, 3, 4, 5] Set[1, 5, 'z'] | (1..6) #=> Set[1, 5, "z", 2, 3, 4, 6]
Source
static VALUE
set_i_add(VALUE set, VALUE item)
{
rb_check_frozen(set);
if (set_iterating_p(set)) {
if (!set_table_lookup(RSET_TABLE(set), (st_data_t)item)) {
no_new_item();
}
}
else {
set_insert_wb(set, item, NULL);
}
return set;
}
将给定对象添加到 Set 并返回 self。使用 Set#merge 一次添加多个元素。
Set[1, 2].add(3) #=> Set[1, 2, 3] Set[1, 2].add([3, 4]) #=> Set[1, 2, [3, 4]] Set[1, 2].add(2) #=> Set[1, 2]
Source
static VALUE
set_i_add_p(VALUE set, VALUE item)
{
rb_check_frozen(set);
if (set_iterating_p(set)) {
if (!set_table_lookup(RSET_TABLE(set), (st_data_t)item)) {
no_new_item();
}
return Qnil;
}
else {
return set_insert_wb(set, item, NULL) ? Qnil : set;
}
}
将给定对象添加到 Set 并返回 self。如果对象已在 Set 中,则返回 nil。
Set[1, 2].add?(3) #=> Set[1, 2, 3] Set[1, 2].add?([3, 4]) #=> Set[1, 2, [3, 4]] Set[1, 2].add?(2) #=> nil
Source
# File ext/json/lib/json/add/set.rb, line 28 def as_json(*) { JSON.create_id => self.class.name, 'a' => to_a, } end
方法 Set#as_json 和 Set.json_create 可用于序列化和反序列化 Set 对象;参见 Marshal。
方法 Set#as_json 序列化 self,返回一个表示 self 的两元素哈希。
require 'json/add/set' x = Set.new(%w/foo bar baz/).as_json # => {"json_class"=>"Set", "a"=>["foo", "bar", "baz"]}
方法 JSON.create 反序列化这样的哈希,返回一个 Set 对象。
Set.json_create(x) # => #<Set: {"foo", "bar", "baz"}>
Source
static VALUE
set_i_classify(VALUE set)
{
RETURN_SIZED_ENUMERATOR(set, 0, 0, set_enum_size);
VALUE args[2];
args[0] = rb_hash_new();
args[1] = rb_obj_class(set);
set_iter(set, set_classify_i, (st_data_t)args);
return args[0];
}
根据给定块的返回值对 Set 进行分类,并返回一个 {value => set of elements} 键值对的哈希表。该块对 Set 中的每个元素调用一次,并将元素作为参数传递。
files = Set.new(Dir.glob("*.rb")) hash = files.classify { |f| File.mtime(f).year } hash #=> {2000 => Set["a.rb", "b.rb"], # 2001 => Set["c.rb", "d.rb", "e.rb"], # 2002 => Set["f.rb"]}
如果未提供块,则返回一个枚举器。
Source
static VALUE
set_i_clear(VALUE set)
{
rb_check_frozen(set);
if (RSET_SIZE(set) == 0) return set;
if (set_iterating_p(set)) {
set_iter(set, set_clear_i, 0);
}
else {
set_table_clear(RSET_TABLE(set));
set_compact_after_delete(set);
}
return set;
}
移除所有元素并返回 self。
set = Set[1, 'c', :s] #=> Set[1, "c", :s] set.clear #=> Set[] set #=> Set[]
Source
static VALUE
set_i_collect(VALUE set)
{
RETURN_SIZED_ENUMERATOR(set, 0, 0, set_enum_size);
rb_check_frozen(set);
VALUE new_set = set_s_alloc(rb_obj_class(set));
set_iter(set, set_collect_i, (st_data_t)new_set);
set_i_initialize_copy(set, new_set);
return set;
}
用 collect 返回的元素替换当前元素。如果没有块,则返回一个枚举器。
Source
static VALUE
set_i_compare_by_identity(VALUE set)
{
if (RSET_COMPARE_BY_IDENTITY(set)) return set;
if (set_iterating_p(set)) {
rb_raise(rb_eRuntimeError, "compare_by_identity during iteration");
}
return set_reset_table_with_type(set, &identhash);
}
使 Set 仅根据其身份来比较元素,并返回 self。
Source
static VALUE
set_i_compare_by_identity_p(VALUE set)
{
return RBOOL(RSET_COMPARE_BY_IDENTITY(set));
}
返回 Set 是否会根据其身份比较元素。另请参见 Set#compare_by_identity。
Source
static VALUE
set_i_delete(VALUE set, VALUE item)
{
rb_check_frozen(set);
if (set_table_delete(RSET_TABLE(set), (st_data_t *)&item)) {
set_compact_after_delete(set);
}
return set;
}
从 Set 中删除给定对象并返回 self。使用 subtract 一次删除多个项。
Source
static VALUE
set_i_delete_p(VALUE set, VALUE item)
{
rb_check_frozen(set);
if (set_table_delete(RSET_TABLE(set), (st_data_t *)&item)) {
set_compact_after_delete(set);
return set;
}
return Qnil;
}
从 Set 中删除给定对象并返回 self。如果对象不在 Set 中,则返回 nil。
Source
static VALUE
set_i_delete_if(VALUE set)
{
RETURN_SIZED_ENUMERATOR(set, 0, 0, set_enum_size);
rb_check_frozen(set);
set_iter(set, set_delete_if_i, 0);
set_compact_after_delete(set);
return set;
}
删除 Set 中所有块求值为 true 的元素,并返回 self。如果没有块,则返回一个枚举器。
Source
static VALUE
set_i_disjoint(VALUE set, VALUE other)
{
return RBOOL(!RTEST(set_i_intersect(set, other)));
}
如果 Set 和给定的 enumerable 对象没有共同元素,则返回 true。此方法与 intersect? 相反。
Set[1, 2, 3].disjoint? Set[3, 4] #=> false Set[1, 2, 3].disjoint? Set[4, 5] #=> true Set[1, 2, 3].disjoint? [3, 4] #=> false Set[1, 2, 3].disjoint? 4..5 #=> true
Source
static VALUE
set_i_divide(VALUE set)
{
RETURN_SIZED_ENUMERATOR(set, 0, 0, set_enum_size);
if (rb_block_arity() == 2) {
return set_divide_arity2(set);
}
VALUE values = rb_hash_values(set_i_classify(set));
set = set_alloc_with_size(rb_cSet, RARRAY_LEN(values));
set_merge_enum_into(set, values);
return set;
}
根据给定块定义的共同性将 Set 分割为一组子集。
如果块的元数是 2,则当 block.call(o1, o2) 和 block.call(o2, o1) 都为 true 时,元素 o1 和 o2 被认为是共同的。否则,当 block.call(o1) == block.call(o2) 时,元素 o1 和 o2 被认为是共同的。
numbers = Set[1, 3, 4, 6, 9, 10, 11] set = numbers.divide { |i,j| (i - j).abs == 1 } set #=> Set[Set[1], # Set[3, 4], # Set[6], # Set[9, 10, 11]]
如果未提供块,则返回一个枚举器。
Source
static VALUE
set_i_each(VALUE set)
{
RETURN_SIZED_ENUMERATOR(set, 0, 0, set_enum_size);
set_iter(set, set_each_i, 0);
return set;
}
为 Set 中的每个元素调用一次给定的块,并将元素作为参数传递。如果没有块,则返回一个枚举器。
Source
static VALUE
set_i_empty(VALUE set)
{
return RBOOL(RSET_EMPTY(set));
}
如果 Set 不包含任何元素,则返回 true。
Source
# File ext/psych/lib/psych/core_ext.rb, line 23 def encode_with(coder) hash = {} each do |m| hash[m] = true end coder["hash"] = hash coder end
Source
static VALUE
set_i_flatten(VALUE set)
{
VALUE new_set = set_s_alloc(rb_obj_class(set));
set_flatten_merge(new_set, set, rb_hash_new());
return new_set;
}
返回一个 Set 的副本,并递归地展平其中包含的 Set。
Source
static VALUE
set_i_flatten_bang(VALUE set)
{
bool contains_set = false;
set_iter(set, set_contains_set_i, (st_data_t)&contains_set);
if (!contains_set) return Qnil;
rb_check_frozen(set);
return set_i_replace(set, set_i_flatten(set));
}
等同于 Set#flatten,但将接收者原地替换为结果。如果未进行任何修改,则返回 nil。
Source
static VALUE
set_i_hash(VALUE set)
{
st_index_t size = RSET_SIZE(set);
st_index_t hval = rb_st_hash_start(size);
hval = rb_hash_uint(hval, (st_index_t)set_i_hash);
if (size) {
set_iter(set, set_hash_i, (VALUE)&hval);
}
hval = rb_st_hash_end(hval);
return ST2FIX(hval);
}
返回 Set 的哈希码。
Source
static VALUE
set_i_include(VALUE set, VALUE item)
{
return RBOOL(RSET_IS_MEMBER(set, item));
}
如果 Set 包含给定的对象,则返回 true。
Set[1, 2, 3].include? 2 #=> true Set[1, 2, 3].include? 4 #=> false
请注意,include? 和 member? 不像其他 Enumerable 对象那样使用 == 测试成员相等性。
这别名为 ===,因此可以在 case 表达式中使用。
case :apple when Set[:potato, :carrot] "vegetable" when Set[:apple, :banana] "fruit" end # => "fruit"
另请参见 Enumerable#include?。
Source
# File ext/psych/lib/psych/core_ext.rb, line 32 def init_with(coder) replace(coder["hash"].keys) end
Source
static VALUE
set_i_inspect(VALUE set)
{
return rb_exec_recursive(set_inspect, set, 0);
}
返回一个包含 Set 条目的新字符串。
s = Set.new s.inspect # => "Set[]" s.add(1) s.inspect # => "Set[1]" s.add(2) s.inspect # => "Set[1, 2]"
相关:参见 转换为其他格式的方法。
Source
static VALUE
set_i_intersect(VALUE set, VALUE other)
{
if (rb_obj_is_kind_of(other, rb_cSet)) {
size_t set_size = RSET_SIZE(set);
size_t other_size = RSET_SIZE(other);
VALUE args[2];
args[1] = Qfalse;
VALUE iter_arg;
if (set_size < other_size) {
iter_arg = set;
args[0] = (VALUE)RSET_TABLE(other);
}
else {
iter_arg = other;
args[0] = (VALUE)RSET_TABLE(set);
}
set_iter(iter_arg, set_intersect_i, (st_data_t)args);
return args[1];
}
else if (rb_obj_is_kind_of(other, rb_mEnumerable)) {
return rb_funcall(other, id_any_p, 1, set);
}
else {
rb_raise(rb_eArgError, "value must be enumerable");
}
}
如果 Set 和给定的 enumerable 对象至少有一个共同元素,则返回 true。
Set[1, 2, 3].intersect? Set[4, 5] #=> false Set[1, 2, 3].intersect? Set[3, 4] #=> true Set[1, 2, 3].intersect? 4..5 #=> false Set[1, 2, 3].intersect? [3, 4] #=> true
Source
static VALUE
set_i_join(int argc, VALUE *argv, VALUE set)
{
rb_check_arity(argc, 0, 1);
return rb_ary_join(set_i_to_a(set), argc == 0 ? Qnil : argv[0]);
}
返回一个字符串,该字符串是通过将 Set 中的每个元素转换为字符串而创建的。
Source
static VALUE
set_i_keep_if(VALUE set)
{
RETURN_SIZED_ENUMERATOR(set, 0, 0, set_enum_size);
rb_check_frozen(set);
set_iter(set, set_keep_if_i, (st_data_t)RSET_TABLE(set));
return set;
}
删除 Set 中所有块求值为 false 的元素,并返回 self。如果没有块,则返回一个枚举器。
Source
static VALUE
set_i_merge(int argc, VALUE *argv, VALUE set)
{
if (rb_keyword_given_p()) {
rb_raise(rb_eArgError, "no keywords accepted");
}
if (set_iterating_p(set)) {
rb_raise(rb_eRuntimeError, "cannot add to set during iteration");
}
rb_check_frozen(set);
int i;
for (i=0; i < argc; i++) {
set_merge_enum_into(set, argv[i]);
}
return set;
}
将给定 enumerable 对象中的元素合并到 Set 中,并返回 self。
Source
static VALUE
set_i_proper_subset(VALUE set, VALUE other)
{
check_set(other);
if (RSET_SIZE(set) >= RSET_SIZE(other)) return Qfalse;
return set_le(set, other);
}
如果 Set 是给定 Set 的真子集,则返回 true。
Source
static VALUE
set_i_proper_superset(VALUE set, VALUE other)
{
check_set(other);
if (RSET_SIZE(set) <= RSET_SIZE(other)) return Qfalse;
return set_le(other, set);
}
如果 Set 是给定 Set 的真超集,则返回 true。
Source
static VALUE
set_i_reject(VALUE set)
{
RETURN_SIZED_ENUMERATOR(set, 0, 0, set_enum_size);
rb_check_frozen(set);
set_table *table = RSET_TABLE(set);
size_t n = set_table_size(table);
set_iter(set, set_delete_if_i, 0);
if (n == set_table_size(table)) return Qnil;
set_compact_after_delete(set);
return set;
}
等同于 Set#delete_if,但如果没有进行任何更改,则返回 nil。如果没有块,则返回一个枚举器。
Source
static VALUE
set_i_replace(VALUE set, VALUE other)
{
rb_check_frozen(set);
if (rb_obj_is_kind_of(other, rb_cSet)) {
set_i_initialize_copy(set, other);
}
else {
if (set_iterating_p(set)) {
rb_raise(rb_eRuntimeError, "cannot replace set during iteration");
}
// make sure enum is enumerable before calling clear
enum_method_id(other);
set_table_clear(RSET_TABLE(set));
set_merge_enum_into(set, other);
}
return set;
}
用给定 enumerable 对象中的内容替换 Set 的内容,并返回 self。
set = Set[1, 'c', :s] #=> Set[1, "c", :s] set.replace([1, 2]) #=> Set[1, 2] set #=> Set[1, 2]
Source
static VALUE
set_i_reset(VALUE set)
{
if (set_iterating_p(set)) {
rb_raise(rb_eRuntimeError, "reset during iteration");
}
return set_reset_table_with_type(set, RSET_TABLE(set)->type);
}
在修改现有元素后重置内部状态,并返回 self。元素将被重新索引和去重。
Source
static VALUE
set_i_select(VALUE set)
{
RETURN_SIZED_ENUMERATOR(set, 0, 0, set_enum_size);
rb_check_frozen(set);
set_table *table = RSET_TABLE(set);
size_t n = set_table_size(table);
set_iter(set, set_keep_if_i, (st_data_t)table);
return (n == set_table_size(table)) ? Qnil : set;
}
等同于 Set#keep_if,但如果没有进行任何更改,则返回 nil。如果没有块,则返回一个枚举器。
Source
static VALUE
set_i_subset(VALUE set, VALUE other)
{
check_set(other);
if (RSET_SIZE(set) > RSET_SIZE(other)) return Qfalse;
return set_le(set, other);
}
如果 Set 是给定 Set 的子集,则返回 true。
Source
static VALUE
set_i_subtract(VALUE set, VALUE other)
{
rb_check_frozen(set);
set_remove_enum_from(set, other);
return set;
}
删除在给定 enumerable 对象中出现的所有元素,并返回 self。
Source
static VALUE
set_i_superset(VALUE set, VALUE other)
{
check_set(other);
if (RSET_SIZE(set) < RSET_SIZE(other)) return Qfalse;
return set_le(other, set);
}
如果 Set 是给定 Set 的超集,则返回 true。
Source
static VALUE
set_i_to_a(VALUE set)
{
st_index_t size = RSET_SIZE(set);
VALUE ary = rb_ary_new_capa(size);
if (size == 0) return ary;
if (ST_DATA_COMPATIBLE_P(VALUE)) {
RARRAY_PTR_USE(ary, ptr, {
size = set_keys(RSET_TABLE(set), ptr, size);
});
rb_gc_writebarrier_remember(ary);
rb_ary_set_len(ary, size);
}
else {
set_iter(set, set_to_a_i, (st_data_t)ary);
}
return ary;
}
返回一个包含 Set 中所有元素的数组。
Set[1, 2].to_a #=> [1, 2] Set[1, 'c', :s].to_a #=> [1, "c", :s]
Source
# File ext/json/lib/json/add/set.rb, line 44 def to_json(*args) as_json.to_json(*args) end
返回一个代表 self 的 JSON 字符串
require 'json/add/set' puts Set.new(%w/foo bar baz/).to_json
输出
{"json_class":"Set","a":["foo","bar","baz"]}
Source
static VALUE
set_i_to_set(int argc, VALUE *argv, VALUE set)
{
VALUE klass;
if (argc == 0) {
klass = rb_cSet;
argv = &set;
argc = 1;
}
else {
rb_warn_deprecated("passing arguments to Set#to_set", NULL);
klass = argv[0];
argv[0] = set;
}
if (klass == rb_cSet && rb_obj_is_instance_of(set, rb_cSet) &&
argc == 1 && !rb_block_given_p()) {
return set;
}
return rb_funcall_passing_block(klass, id_new, argc, argv);
}
不带参数时,返回 self(用于接受“Set 或可转换为 Set”的参数的方法中的鸭子类型)。
带参数的形式已**弃用**。它将 Set 转换为另一个 Set,使用 klass.new(self, *args, &block)。