# # 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 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 # can be converted to Set using the `to_set` method. # Set uses Hash as storage, so you must note the following points: # * Equality of elements is determined according to Object#eql? and # Object#hash. Use Set#compare_by_identity to make a set compare # its elements by their identity. # * Set assumes that the identity of each element does not change # while it is stored. Modifying an element of a set will render the # set to an unreliable state. # * When a string is to be stored, a frozen copy of the string is # stored instead unless the original string is already frozen. # # ## Comparison # The comparison operators `<`, `>`, `<=`, and `>=` are implemented as # shorthand for the {proper_,}{subset?,superset?} methods. The `<=>` # operator reflects this order, or return `nil` for sets that both # have distinct elements (`{x, y}` vs. `{x, z}` for example). # ## Example # require 'set' # s1 = Set[1, 2] #=> # # s2 = [1, 2].to_set #=> # # s1 == s2 #=> true # s1.add("foo") #=> # # s1.merge([2, 6]) #=> # # s1.subset?(s2) #=> false # s2.subset?(s1) #=> true # # ## Contact # * Akinori MUSHA (current maintainer) # # ## What's Here # First, what's elsewhere. Class Set: # * 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 # for fetching or for iterating. # Instead, it relies on those in Enumerable. # Here, class Set provides methods that are useful for: # * [Creating a Set](#class-Set-label-Methods+for+Creating+a+Set) # * [Set Operations](#class-Set-label-Methods+for+Set+Operations) # * [Comparing](#class-Set-label-Methods+for+Comparing) # * [Querying](#class-Set-label-Methods+for+Querying) # * [Assigning](#class-Set-label-Methods+for+Assigning) # * [Deleting](#class-Set-label-Methods+for+Deleting) # * [Converting](#class-Set-label-Methods+for+Converting) # * [Iterating](#class-Set-label-Methods+for+Iterating) # * [And more....](#class-Set-label-Other+Methods) # # ### Methods for Creating a Set # * ::[]: # Returns a new set containing the given objects. # * ::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 #+): # Returns a new set containing all elements from `self` # and all elements from a given enumerable (no duplicates). # * [&](#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): # Returns a copy of `self` with all elements # in a given enumerable removed. # * [\^](#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): # Returns -1, 0, or 1 as `self` is less than, equal to, # or greater than a given object. # * [==](#method-i-3D-3D): # Returns whether `self` and a given enumerable are equal, # as determined by Object#eql?. # * #compare_by_identity?: # Returns whether the set considers only identity # when comparing elements. # # ### Methods for Querying # * #length (aliased as #size): # Returns the count of elements. # * #empty?: # Returns whether the set has no elements. # * #include? (aliased as #member? and #===): # Returns whether a given object is an element in the set. # * #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)): # Returns whether a given enumerable is a proper subset of the set. # * #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)): # Returns whether a given enumerable is a proper superset of the set. # * #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: # have any common elements, `false` otherwise. # * #compare_by_identity?: # Returns whether the set considers only identity # when comparing elements. # # ### Methods for Assigning # * #add (aliased as #<<): # Adds a given object to the set; returns `self`. # * #add?: # If the given object is not an element in the set, # adds it and returns `self`; otherwise, returns `nil`. # * #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: # Removes all elements in the set; returns `self`. # * #delete: # Removes a given object from the set; returns `self`. # * #delete?: # If the given object is an element in the set, # removes it and returns `self`; otherwise, returns `nil`. # * #subtract: # Removes each given object from the set; returns `self`. # * #delete_if - Removes elements specified by a given block. # * #select! (aliased as #filter!): # Removes elements not specified by a given block. # * #keep_if: # Removes elements not specified by a given block. # * #reject! # Removes elements specified by a given block. # # ### Methods for Converting # * #classify: # Returns a hash that classifies the elements, # as determined by the given block. # * #collect! (aliased as #map!): # Replaces each element with a block return-value. # * #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: # Returns a new set that is a recursive flattening of `self`. # #flatten!: # Replaces each nested set in `self` with the elements from that set. # * #inspect (aliased as #to_s): # Returns a string displaying the elements. # * #join: # Returns a string containing all elements, converted to strings # as needed, and joined by the given record separator. # * #to_a: # Returns an array containing all set elements. # * #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: # Calls the block with each successive element; returns `self`. # # ### Other Methods # * #reset: # Resets the internal state; useful if an object # has been modified while an element in the set. # class Set[unchecked out A] include Enumerable[A] # # Creates a new set containing the elements of the given enumerable # object. # If a block is given, the elements of enum are preprocessed by the # given block. # Set.new([1, 2]) #=> # # Set.new([1, 2, 1]) #=> # # Set.new([1, 'c', :s]) #=> # # Set.new(1..5) #=> # # Set.new([1, 2, 3]) { |x| x * x } #=> # # def initialize: (_Each[A]) -> untyped | [X] (_Each[X]) { (X) -> A } -> untyped | (?nil) -> untyped # # Creates a new set containing the given objects. # Set[1, 2] # => # # Set[1, 2, 1] # => # # Set[1, 'c', :s] # => # # def self.[]: [X] (*X) -> Set[X] # # Returns a new set containing elements common to the set and the # given enumerable object. # Set[1, 3, 5] & Set[3, 2, 1] #=> # # Set['a', 'b', 'z'] & ['a', 'b', 'c'] #=> # # def &: (_Each[A]) -> self # # alias intersection & # # Returns a new set built by merging the set and the elements of the # given enumerable object. # Set[1, 2, 3] | Set[2, 4, 5] #=> # # Set[1, 5, 'z'] | (1..6) #=> # # def |: (_Each[A]) -> self # # alias union | # # alias + | # # Returns a new set built by duplicating the set, removing every # element that appears in the given enumerable object. # Set[1, 3, 5] - Set[1, 5] #=> # # Set['a', 'b', 'z'] - ['a', 'c'] #=> # # def -: (_Each[A]) -> self # # alias difference - # # Adds the given object to the set and returns self. Use `merge` to # add many elements at once. # Set[1, 2].add(3) #=> # # Set[1, 2].add([3, 4]) #=> # # Set[1, 2].add(2) #=> # # def add: (A) -> self # # alias << add # # Adds the given object to the set and returns self. If the # object is already in the set, returns nil. # Set[1, 2].add?(3) #=> # # Set[1, 2].add?([3, 4]) #=> # # Set[1, 2].add?(2) #=> nil # def add?: (A) -> self? # # Returns true if the set contains the given object. # Note that `include?` and `member?` do not test member # equality using `==` as do other Enumerables. # See also Enumerable#include? # def include?: (A) -> bool # # alias member? include? # # Returns a new set containing elements exclusive between the set # and the given enumerable object. `(set ^ enum)` is equivalent to # `((set | enum) - (set & enum))`. # Set[1, 2] ^ Set[2, 3] #=> # # Set[1, 'b', 'c'] ^ ['b', 'd'] #=> # # def ^: (_Each[A]) -> self # # Classifies the set by the return value of the given block and # returns a hash of {value => set of elements} pairs. The block is # called once for each element of the set, passing the element as # parameter. # require 'set' # files = Set.new(Dir.glob("*.rb")) # hash = files.classify { |f| File.mtime(f).year } # hash #=> {2000=>#, # # 2001=>#, # # 2002=>#} # # Returns an enumerator if no block is given. # def classify: [X] () { (A) -> X } -> Hash[X, self] # # Removes all elements and returns self. # set = Set[1, 'c', :s] #=> # # set.clear #=> # # set #=> # # def clear: () -> self # # Replaces the elements with ones returned by `collect()`. # Returns an enumerator if no block is given. # def collect!: () { (A) -> A } -> self # # alias map! collect! # # Deletes the given object from the set and returns self. Use # `subtract` to delete many items at once. # def delete: (A) -> self # # Deletes the given object from the set and returns self. If the # object is not in the set, returns nil. # def delete?: (A) -> self? # # Deletes every element of the set for which block evaluates to # true, and returns self. Returns an enumerator if no block is # given. # def delete_if: () { (A) -> untyped } -> self # # Equivalent to Set#delete_if, but returns nil if no changes were # made. Returns an enumerator if no block is given. # def reject!: () { (A) -> untyped } -> self # # Makes the set compare its elements by their identity and returns # self. This method may not be supported by all subclasses of Set. # def compare_by_identity: () -> self # # Returns true if the set and the given enumerable have # no element in common. This method is the opposite of `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 # def disjoint?: (_Each[A]) -> bool # # Divides the set into a set of subsets according to the commonality # defined by the given block. # If the arity of the block is 2, elements o1 and o2 are in common # if block.call(o1, o2) is true. Otherwise, elements o1 and o2 are # in common if block.call(o1) == block.call(o2). # require 'set' # numbers = Set[1, 3, 4, 6, 9, 10, 11] # set = numbers.divide { |i,j| (i - j).abs == 1 } # set #=> #, # # #, # # #, # # #}> # # Returns an enumerator if no block is given. # def divide: () { (A, A) -> untyped } -> Set[self] | () { (A) -> untyped } -> Set[self] # # Calls the given block once for each element in the set, passing # the element as parameter. Returns an enumerator if no block is # given. # def each: () { (A) -> void } -> self | () -> Enumerator[A, self] # # Returns true if the set contains no elements. # def empty?: () -> bool # # Returns a new set that is a copy of the set, flattening each # containing set recursively. # def flatten: () -> Set[untyped] # # Returns true if the set and the given enumerable have at least one # element in common. # 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 # def intersect?: (_Each[A]) -> bool # # Deletes every element of the set for which block evaluates to # false, and returns self. Returns an enumerator if no block is # given. # def keep_if: () { (A) -> untyped } -> self # # Returns the number of elements. # def size: () -> Integer # # alias length size # # Merges the elements of the given enumerable objects to the set and # returns self. # def merge: (_Each[A]) -> self # # Returns true if the set is a subset of the given set. # def subset?: (self) -> bool def proper_subst?: (self) -> bool # # Returns true if the set is a superset of the given set. # def superset?: (self) -> bool # # Returns true if the set is a proper superset of the given set. # def proper_superset?: (self) -> bool # # Replaces the contents of the set with the contents of the given # enumerable object and returns self. # set = Set[1, 'c', :s] #=> # # set.replace([1, 2]) #=> # # set #=> # # def replace: (_Each[A]) -> self # # Resets the internal state after modification to existing elements # and returns self. # Elements will be reindexed and deduplicated. # def reset: () -> self # # Equivalent to Set#keep_if, but returns nil if no changes were # made. Returns an enumerator if no block is given. # def select!: () { (A) -> untyped } -> self? # # Deletes every element that appears in the given enumerable object # and returns self. # def subtract: (_Each[A]) -> self # # Converts the set to an array. The order of elements is uncertain. # Set[1, 2].to_a #=> [1, 2] # Set[1, 'c', :s].to_a #=> [1, "c", :s] # def to_a: () -> Array[A] end %a{annotate:rdoc:skip} module Enumerable[unchecked out Elem] # # Makes a set from the enumerable object with given arguments. # Needs to `require "set"` to use this method. # def to_set: () -> Set[Elem] | [T] { (Elem) -> T } -> Set[T] end