Ruby/Collections/Set

Материал из Wiki.crossplatform.ru

Перейти к: навигация, поиск

Содержание

a-b: is the elements of a except for those also in b

require "set"
primes = Set[2, 3, 5, 7]
odds = Set[1, 3, 5, 7, 9]
p primes-odds               # => #<Set: {2}>
p odds-primes               # => #<Set: {1, 9}>
p primes.difference(odds)   # A named method alias



a^b is the set of values that appear in one set but not both: (a|b)-(a&b)

require "set"
primes = Set[2, 3, 5, 7]
odds = Set[1, 3, 5, 7, 9]
primes ^ odds             # => #<Set: {1, 2, 9}>



Add element to a set

require "set"
s = Set[]              # start with an empty set
s << 1                 # => #<Set: {1}>
s.add 2                # => #<Set: {1, 2}>: add is a synonym for <<
s << 3 << 4 << 5       # => #<Set: {5, 1, 2, 3, 4}>: can be chained
s.add 3                # => #<Set: {5, 1, 2, 3, 4}>: value unchanged
s.add? 6               # => #<Set: {5, 6, 1, 2, 3, 4}>
s.add? 3               # => nil: the set was not changed



Add new method to set

require "set"
class OrderedSet < Set
  def initialize
    @hash ||= OrderedHash.new
  end
end



Add set operation to Array

require "set"
 
class Array
  def classify
 
    h = {}
    each do |i|
      x = yield(i)
      (h[x] ||= self.class.new) << i
    end
    h
  end
  def divide(&block)
    Set.new(classify(&block).values)
  end
end
p [1,1,2,6,6,7,101].divide { |x| x % 2 }
# => #<Set: {[2, 6, 6], [1, 1, 7, 101]}>



Classify a set into three

require "set"
s = ["a","b","c",1, 2, 3, -1.0, -2.0, -4.0].to_set
p s.classify { |x| x.class }



Classify set elements as even or odd

require "set"
s = (0..3).to_set     # => #<Set: {0, 1, 2, 3}>
s.classify {|x| x%2}  # => {0=>#<Set: {0, 2}>, 1=>#<Set: {1, 3}>}



Clear a set

require "set"
s = Set.new(1..3) # Initial set
s.clear           # => #<Set: {}>



Collect in place

require "set"
s = Set[1, 2, 3, 4, 5] # => #<Set: {5, 1, 2, 3, 4}>
s.collect! {|x| x/2 }  # => #<Set: {0, 12, 2, 8, 4}>



Compare two sets

require "set"
s = (1..3).to_set
s == Set[3,2,1] # => true: uses eql? to compare set elements



Convert a hash to set and divide

require "set"
connections = { 1 => 2, 2 => 3, 3 => 1, 4 => 1 }
[1,2,3,4].to_set.divide { |x,y| connections[x] == y }
# => #<Set: {#<Set: {1, 2, 3}>, #<Set: {4}>}>



Convert set to array

require "set"
s = (1..3).to_set
s.to_a          # => [1, 2, 3]



Create set with constant values

require "set"
Set["cow", "pig", "hen"]   # => #<Set: {"cow", "pig", "hen"}>



Create set with Set.new

require "set"
p Set.new(1..5)              # => #<Set: {5, 1, 2, 3, 4}>
p Set.new([1,2,3])           # => #<Set: {1, 2, 3}>
p Set.new([1,2,3]) {|x| x+1} # => #<Set: {2, 3, 4}>



Delete elements from a set with block

require "set"
primes = Set[2, 3, 5, 7]       # set of prime numbers
primes.delete_if {|x| x%2==1}  # => #<Set: {2}>: remove odds
primes.delete_if {|x| x%2==1}  # => #<Set: {2}>: unchanged



Divide a set by absolute value

require "set"
 
s = [1, 2, 3, -1, -2, -4].to_set
# Divide the set into sets of numbers with the same absolute value.
p s.divide { |x,y| x.abs == y.abs }
# => #<Set: {#<Set: {-1, 1}>,
# =>         #<Set: {2, -2}>,
# =>         #<Set: {-4}>,
# =>         #<Set: {3}>}>



Divide a set by even and odd value

require "set"
s = Set.new((1..10).collect)
# Divide the set into the "0" subset and the "1" subset: that is, the
# "even" subset and the "odd" subset.
p s.divide { |x| x % 2 }
# => #<Set: {#<Set: {6, 2, 8, 4, 10}>, #<Set: {5, 1, 7, 3, 9}>}>



Divide a set by its element"s class

require "set"
s = Set.new([1, 2, 3, "a", "b", "c", -1.0, -2.0, -3.0])
# Divide the set into the "String subset, the "Fixnum" subset, and the
# "Float" subset.
p s.divide { |x| x.class }
# => #<Set: {#<Set: {"a", "b", "c"}>,
# =>         #<Set: {1, 2, 3}>,
# =>         #<Set: {-1.0, -3.0, -2.0}>}>



Divide a set by value

require "set"
s = Set.new((1..10).collect)
# Divide the set into the "true" subset and the "false" subset: that
# is, the "less than 5" subset and the "not less than 5" subset.
p s.divide { |x| x < 5 }
# => #<Set: {#<Set: {5, 6, 7, 8, 9, 10}>, #<Set: {1, 2, 3, 4}>}>



Divide set

require "set"
s = (0..3).to_set     # => #<Set: {0, 1, 2, 3}>
s.divide {|x| x%2}  # => #<Set: {#<Set: {0, 2}>, #<Set: {1, 3}>}>



Divide set into three sub sets

require "set"
s = [1, 2, 3, -1, -2, -4].to_set
# Divide the set into sets of adjacent numbers
p s.divide { |x,y| (x-y).abs == 1 }
# => #<Set: {#<Set: {1, 2, 3}>,
# =>         #<Set: {-1}>,
# =>         #<Set: {-4, -3}>}>



Divide with block

require "set"
s = %w[ant ape cow hen hog].to_set # A set of words
s.divide {|x,y| x[0] == y[0]}      # Divide into subsets by first letter
# => #<Set:{#<Set:{"hog", "hen"}>, #<Set:{"cow"}>, #<Set:{"ape", "ant"}>}>



Do an in-place intersection like this:

require "set"
s = (1..5).to_set
t = (4..8).to_set
s.reject! {|x| not t.include? x}  # => #<Set: {5, 4}>



Each loop

require "set"
s = Set[1, 2, 3, 4, 5] # => #<Set: {5, 1, 2, 3, 4}>
s.each {|x| print x }  # prints "51234": arbitrary order before Ruby 1.9



Flatten the subsets

require "set"
s = %w[ant ape cow hen hog].to_set # A set of words
t = s.divide {|x,y| x[0] == y[0]}  # Divide it into subsets
t.flatten!                         # Flatten the subsets
t == s                             # => true



Inspect a set

require "set"
s = (1..3).to_set
s.inspect       # => "#<Set: {1, 2, 3}>": useful



Is it a subset

require "set"
s = Set[2, 3, 5]
t = Set[2, 3, 5, 7]
p s.subset? t            # => true
p t.subset? s            # => false
p s.proper_subset? t     # => true
p t.superset? s          # => true
p t.proper_superset? s   # => true
p s.subset? s            # => true
p s.proper_subset? s     # => false



Is it empty

require "set"
 
s = Set.new(1..3) # Initial set
s.empty?          # => true



Is it in a set

require "set"
s = Set.new(1..3)   # => #<Set: {1, 2, 3}>
p s.include? 1        # => true
p s.member? 0         # => false: member? is a synonym



Map elements in a set

require "set"
s = Set[1, 2, 3, 4, 5] # => #<Set: {5, 1, 2, 3, 4}>
s.map! {|x| x*x }      # => #<Set: {16, 1, 25, 9, 4}>



merge a range to a set

require "set"
s = (1..3).to_set   # => #<Set: {1, 2, 3}>
s.merge(2..5)       # => #<Set: {5, 1, 2, 3, 4}>



Partitioning or Classifying a Set

require "set"
p s = Set.new((1..10).collect)
# => #<Set: {5, 6, 1, 7, 2, 8, 3, 9, 4, 10}>



Reject elements from a set

require "set"
primes = Set[2, 3, 5, 7]       # set of prime numbers
primes.reject! {|x| x%2==1}    # => nil: unchanged



Remove elements from a set

require "set"
s = (1..3).to_set   # => #<Set: {1, 2, 3}>
s.delete 1          # => #<Set: {2, 3}>
s.delete 1          # => #<Set: {2, 3}>: unchanged
s.delete? 1         # => nil: returns nil when no change
s.delete? 2         # => #<Set: {3}>: otherwise returns set



Replace a set

require "set"
s = Set.new(1..3) # Initial set
s.replace(3..4)   # Replace all elements.  Argument is any enumerable



Set includes and membership

require "set"
primes = Set[2, 3, 5, 7]
primes.include? 2        # => true
primes.member? 1         # => false



Set length, size and empty?

require "set"
s = Set[2, 3, 5]
p s.length               # => 3
p s.size                 # => 3: a synonym for length
p s.empty?               # => false
p Set.new.empty?         # => true



Set subtraction

require "set"
s = (1..3).to_set   # => #<Set: {1, 2, 3}>
s.subtract(2..10)   # => #<Set: {1}>



Sort with block

require "set"
w = Set["apple","Beet","carrot"]  # A set of words to sort
w.sort                         # ["Beet","apple","carrot"]: alphabetical
w.sort {|a,b| b<=>a }          # ["carrot","apple","Beet"]: reverse
w.sort {|a,b| a.casecmp(b) }   # ["apple","Beet","carrot"]: ignore case
w.sort {|a,b| b.size<=>a.size} # ["carrot","apple","Beet"]: reverse length



The intersection is the set of values that appear in both

require "set"
primes = Set[2, 3, 5, 7]
odds = Set[1, 3, 5, 7, 9]
p primes & odds             # => #<Set: {5, 7, 3}>
p primes.intersection(odds) # this is an explicitly named alias



The union is the set of values that appear in either

require "set"
primes = Set[2, 3, 5, 7]
odds = Set[1, 3, 5, 7, 9]
p primes | odds             # => #<Set: {5, 1, 7, 2, 3, 9}>
p primes.union(odds)        # an explicitly named alias