summaryrefslogtreecommitdiff
path: root/lib/set.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/set.rb')
-rw-r--r--lib/set.rb165
1 files changed, 79 insertions, 86 deletions
diff --git a/lib/set.rb b/lib/set.rb
index 50399309e3..a0954a31d1 100644
--- a/lib/set.rb
+++ b/lib/set.rb
@@ -3,7 +3,7 @@
#
# set.rb - defines the Set class
#
-# Copyright (c) 2002-2020 Akinori MUSHA <knu@iDaemons.org>
+# Copyright (c) 2002-2023 Akinori MUSHA <knu@iDaemons.org>
#
# Documentation by Akinori MUSHA and Gavin Sinclair.
#
@@ -12,16 +12,12 @@
##
-# This library provides the Set class, which deals with a collection
-# of unordered values with no duplicates. It is a hybrid of Array's
+# This library provides the Set class, which implements a collection
+# of unordered values with no duplicates. It is a hybrid of Array's
# intuitive inter-operation facilities and Hash's fast lookup.
#
# The method `to_set` is added to Enumerable for convenience.
#
-# Set implements a collection of unordered values with no duplicates.
-# This is a hybrid of Array's intuitive inter-operation facilities and
-# Hash's fast lookup.
-#
# Set is easy to use with Enumerable objects (implementing `each`).
# Most of the initializer methods and binary operators accept generic
# Enumerable objects besides sets and arrays. An Enumerable object
@@ -66,8 +62,8 @@
#
# First, what's elsewhere. \Class \Set:
#
-# - Inherits from {class Object}[https://docs.ruby-lang.org/en/master/Object.html#class-Object-label-What-27s+Here].
-# - Includes {module Enumerable}[https://docs.ruby-lang.org/en/master/Enumerable.html#module-Enumerable-label-What-27s+Here],
+# - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
+# - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
# which provides dozens of additional methods.
#
# In particular, class \Set does not have many methods of its own
@@ -88,138 +84,140 @@
#
# ### Methods for Creating a \Set
#
-# - ::[] -
+# - ::[]:
# Returns a new set containing the given objects.
-# - ::new -
+# - ::new:
# Returns a new set containing either the given objects
# (if no block given) or the return values from the called block
# (if a block given).
#
# ### Methods for \Set Operations
#
-# - [|](#method-i-7C) (aliased as #union and #+) -
+# - [|](#method-i-7C) (aliased as #union and #+):
# Returns a new set containing all elements from +self+
# and all elements from a given enumerable (no duplicates).
-# - [&](#method-i-26) (aliased as #intersection) -
+# - [&](#method-i-26) (aliased as #intersection):
# Returns a new set containing all elements common to +self+
# and a given enumerable.
-# - [-](#method-i-2D) (aliased as #difference) -
+# - [-](#method-i-2D) (aliased as #difference):
# Returns a copy of +self+ with all elements
# in a given enumerable removed.
-# - [\^](#method-i-5E) -
+# - [\^](#method-i-5E):
# Returns a new set containing all elements from +self+
# and a given enumerable except those common to both.
#
# ### Methods for Comparing
#
-# - [<=>](#method-i-3C-3D-3E) -
+# - [<=>](#method-i-3C-3D-3E):
# Returns -1, 0, or 1 as +self+ is less than, equal to,
# or greater than a given object.
-# - [==](#method-i-3D-3D) -
+# - [==](#method-i-3D-3D):
# Returns whether +self+ and a given enumerable are equal,
# as determined by Object#eql?.
-# - \#compare_by_identity? -
+# - \#compare_by_identity?:
# Returns whether the set considers only identity
# when comparing elements.
#
# ### Methods for Querying
#
-# - \#length (aliased as #size) -
+# - \#length (aliased as #size):
# Returns the count of elements.
-# - \#empty? -
+# - \#empty?:
# Returns whether the set has no elements.
-# - \#include? (aliased as #member? and #===) -
+# - \#include? (aliased as #member? and #===):
# Returns whether a given object is an element in the set.
-# - \#subset? (aliased as [<=](#method-i-3C-3D)) -
+# - \#subset? (aliased as [<=](#method-i-3C-3D)):
# Returns whether a given object is a subset of the set.
-# - \#proper_subset? (aliased as [<](#method-i-3C)) -
+# - \#proper_subset? (aliased as [<](#method-i-3C)):
# Returns whether a given enumerable is a proper subset of the set.
-# - \#superset? (aliased as [<=](#method-i-3E-3D])) -
+# - \#superset? (aliased as [>=](#method-i-3E-3D])):
# Returns whether a given enumerable is a superset of the set.
-# - \#proper_superset? (aliased as [>](#method-i-3E)) -
+# - \#proper_superset? (aliased as [>](#method-i-3E)):
# Returns whether a given enumerable is a proper superset of the set.
-# - \#disjoint? -
+# - \#disjoint?:
# Returns +true+ if the set and a given enumerable
# have no common elements, +false+ otherwise.
-# - \#intersect? -
-# Returns +true+ if the set and a given enumerable -
+# - \#intersect?:
+# Returns +true+ if the set and a given enumerable:
# have any common elements, +false+ otherwise.
-# - \#compare_by_identity? -
+# - \#compare_by_identity?:
# Returns whether the set considers only identity
# when comparing elements.
#
# ### Methods for Assigning
#
-# - \#add (aliased as #<<) -
+# - \#add (aliased as #<<):
# Adds a given object to the set; returns +self+.
-# - \#add? -
+# - \#add?:
# If the given object is not an element in the set,
# adds it and returns +self+; otherwise, returns +nil+.
-# - \#merge -
-# Adds each given object to the set; returns +self+.
-# - \#replace -
+# - \#merge:
+# Merges the elements of each given enumerable object to the set; returns +self+.
+# - \#replace:
# Replaces the contents of the set with the contents
# of a given enumerable.
#
# ### Methods for Deleting
#
-# - \#clear -
+# - \#clear:
# Removes all elements in the set; returns +self+.
-# - \#delete -
+# - \#delete:
# Removes a given object from the set; returns +self+.
-# - \#delete? -
+# - \#delete?:
# If the given object is an element in the set,
# removes it and returns +self+; otherwise, returns +nil+.
-# - \#subtract -
+# - \#subtract:
# Removes each given object from the set; returns +self+.
# - \#delete_if - Removes elements specified by a given block.
-# - \#select! (aliased as #filter!) -
+# - \#select! (aliased as #filter!):
# Removes elements not specified by a given block.
-# - \#keep_if -
+# - \#keep_if:
# Removes elements not specified by a given block.
# - \#reject!
# Removes elements specified by a given block.
#
# ### Methods for Converting
#
-# - \#classify -
+# - \#classify:
# Returns a hash that classifies the elements,
# as determined by the given block.
-# - \#collect! (aliased as #map!) -
+# - \#collect! (aliased as #map!):
# Replaces each element with a block return-value.
-# - \#divide -
+# - \#divide:
# Returns a hash that classifies the elements,
# as determined by the given block;
# differs from #classify in that the block may accept
# either one or two arguments.
-# - \#flatten -
+# - \#flatten:
# Returns a new set that is a recursive flattening of +self+.
-# \#flatten! -
+# \#flatten!:
# Replaces each nested set in +self+ with the elements from that set.
-# - \#inspect (aliased as #to_s) -
+# - \#inspect (aliased as #to_s):
# Returns a string displaying the elements.
-# - \#join -
+# - \#join:
# Returns a string containing all elements, converted to strings
# as needed, and joined by the given record separator.
-# - \#to_a -
+# - \#to_a:
# Returns an array containing all set elements.
-# - \#to_set -
+# - \#to_set:
# Returns +self+ if given no arguments and no block;
# with a block given, returns a new set consisting of block
# return values.
#
# ### Methods for Iterating
#
-# - \#each -
+# - \#each:
# Calls the block with each successive element; returns +self+.
#
# ### Other Methods
#
-# - \#reset -
+# - \#reset:
# Resets the internal state; useful if an object
# has been modified while an element in the set.
#
class Set
+ VERSION = "1.1.0"
+
include Enumerable
# Creates a new set containing the given objects.
@@ -288,18 +286,10 @@ class Set
@hash = orig.instance_variable_get(:@hash).dup
end
- if Kernel.instance_method(:initialize_clone).arity != 1
- # Clone internal hash.
- def initialize_clone(orig, **options)
- super
- @hash = orig.instance_variable_get(:@hash).clone(**options)
- end
- else
- # Clone internal hash.
- def initialize_clone(orig)
- super
- @hash = orig.instance_variable_get(:@hash).clone
- end
+ # Clone internal hash.
+ def initialize_clone(orig, **options)
+ super
+ @hash = orig.instance_variable_get(:@hash).clone(**options)
end
def freeze # :nodoc:
@@ -391,7 +381,7 @@ class Set
# Equivalent to Set#flatten, but replaces the receiver with the
# result in place. Returns nil if no modifications were made.
def flatten!
- replace(flatten()) if any? { |e| e.is_a?(Set) }
+ replace(flatten()) if any?(Set)
end
# Returns true if the set contains the given object.
@@ -411,7 +401,7 @@ class Set
when set.instance_of?(self.class) && @hash.respond_to?(:>=)
@hash >= set.instance_variable_get(:@hash)
when set.is_a?(Set)
- size >= set.size && set.all? { |o| include?(o) }
+ size >= set.size && set.all?(self)
else
raise ArgumentError, "value must be a set"
end
@@ -424,7 +414,7 @@ class Set
when set.instance_of?(self.class) && @hash.respond_to?(:>)
@hash > set.instance_variable_get(:@hash)
when set.is_a?(Set)
- size > set.size && set.all? { |o| include?(o) }
+ size > set.size && set.all?(self)
else
raise ArgumentError, "value must be a set"
end
@@ -437,7 +427,7 @@ class Set
when set.instance_of?(self.class) && @hash.respond_to?(:<=)
@hash <= set.instance_variable_get(:@hash)
when set.is_a?(Set)
- size <= set.size && all? { |o| set.include?(o) }
+ size <= set.size && all?(set)
else
raise ArgumentError, "value must be a set"
end
@@ -450,7 +440,7 @@ class Set
when set.instance_of?(self.class) && @hash.respond_to?(:<)
@hash < set.instance_variable_get(:@hash)
when set.is_a?(Set)
- size < set.size && all? { |o| set.include?(o) }
+ size < set.size && all?(set)
else
raise ArgumentError, "value must be a set"
end
@@ -481,12 +471,12 @@ class Set
case set
when Set
if size < set.size
- any? { |o| set.include?(o) }
+ any?(set)
else
- set.any? { |o| include?(o) }
+ set.any?(self)
end
when Enumerable
- set.any? { |o| include?(o) }
+ set.any?(self)
else
raise ArgumentError, "value must be enumerable"
end
@@ -507,7 +497,7 @@ class Set
# the element as parameter. Returns an enumerator if no block is
# given.
def each(&block)
- block or return enum_for(__method__) { size }
+ block_given? or return enum_for(__method__) { size }
@hash.each_key(&block)
self
end
@@ -582,7 +572,7 @@ class Set
# Equivalent to Set#delete_if, but returns nil if no changes were
# made. Returns an enumerator if no block is given.
def reject!(&block)
- block or return enum_for(__method__) { size }
+ block_given? or return enum_for(__method__) { size }
n = size
delete_if(&block)
self if size != n
@@ -591,7 +581,7 @@ class Set
# Equivalent to Set#keep_if, but returns nil if no changes were
# made. Returns an enumerator if no block is given.
def select!(&block)
- block or return enum_for(__method__) { size }
+ block_given? or return enum_for(__method__) { size }
n = size
keep_if(&block)
self if size != n
@@ -600,13 +590,15 @@ class Set
# Equivalent to Set#select!
alias filter! select!
- # Merges the elements of the given enumerable object to the set and
+ # Merges the elements of the given enumerable objects to the set and
# returns self.
- def merge(enum)
- if enum.instance_of?(self.class)
- @hash.update(enum.instance_variable_get(:@hash))
- else
- do_with_enum(enum) { |o| add(o) }
+ def merge(*enums, **nil)
+ enums.each do |enum|
+ if enum.instance_of?(self.class)
+ @hash.update(enum.instance_variable_get(:@hash))
+ else
+ do_with_enum(enum) { |o| add(o) }
+ end
end
self
@@ -834,13 +826,14 @@ class Set
alias to_s inspect
def pretty_print(pp) # :nodoc:
- pp.text sprintf('#<%s: {', self.class.name)
- pp.nest(1) {
- pp.seplist(self) { |o|
- pp.pp o
+ pp.group(1, sprintf('#<%s:', self.class.name), '>') {
+ pp.breakable
+ pp.group(1, '{', '}') {
+ pp.seplist(self) { |o|
+ pp.pp o
+ }
}
}
- pp.text "}>"
end
def pretty_print_cycle(pp) # :nodoc:
@@ -853,7 +846,7 @@ module Enumerable
# Needs to `require "set"` to use this method.
def to_set(klass = Set, *args, &block)
klass.new(self, *args, &block)
- end
+ end unless method_defined?(:to_set)
end
autoload :SortedSet, "#{__dir__}/set/sorted_set"