Class: Hamster::SortedSet

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/hamster/sorted_set.rb

Overview

A SortedSet is a collection of ordered values with no duplicates. Unlike a Vector, in which items can appear in any arbitrary order, a SortedSet always keeps items either in their natural order, or in an order defined by a comparator block which is provided at initialization time.

SortedSet uses #<=> (or its comparator block) to determine which items are equivalent. If the comparator indicates that an existing item and a new item are equal, any attempt to insert the new item will have no effect.

This means that all the items inserted into any one SortedSet must all be comparable. For example, you cannot put Strings and Integers in the same SortedSet. This is unlike Set, which can store items of any type, as long as they all support #hash and #eql?.

A SortedSet can be created in either of the following ways:

Hamster::SortedSet.new([1, 2, 3]) # any Enumerable can be used to initialize
Hamster::SortedSet['A', 'B', 'C', 'D']

Or if you want to use a custom ordering:

Hamster::SortedSet.new([1,2,3]) { |a, b| -a <=> -b }
Hamster::SortedSet.new([1, 2, 3]) { |num| -num }

SortedSet can use a 2-parameter block which returns 0, 1, or -1 as a comparator (like Array#sort), or use a 1-parameter block to derive sort keys (like Array#sort_by) which will be compared using #<=>.

Like all Hamster collections, SortedSets are immutable. Any operation which you might expect to "modify" a SortedSet will actually return a new collection and leave the existing one unchanged.

SortedSet supports the same basic set-theoretic operations as Set, including #union, #intersection, #difference, and #exclusion, as well as #subset?, #superset?, and so on. Unlike Set, it does not define comparison operators like #> or #< as aliases for the superset/subset predicates. Instead, these comparison operators do a item-by-item comparison between the SortedSet and another sequential collection. (See Array#<=> for details.)

Additionally, since SortedSets are ordered, they also support indexed retrieval of items using #at or #[]. Like Vector, negative indices count back from the end of the SortedSet.

Getting the #max or #min item from a SortedSet, as defined by its comparator, is a constant time operation.

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Enumerable

#<=>, #==, #compact, #each_index, #grep, #grep_v, #group_by, #inspect, #join, #partition, #product, #reject, #sum, #to_set

Methods included from Enumerable

#to_list

Constructor Details

#initialize(items = [], &block) ⇒ SortedSet

Returns a new instance of SortedSet.



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/hamster/sorted_set.rb', line 106

def initialize(items=[], &block)
  items = items.to_a
  if block
    # In Ruby 2, &:method blocks have arity -1; in Ruby 3, it's -2
    if block.arity == 1 || block.arity == -1 || block.arity == -2
      items = items.uniq(&block)
      items.sort_by!(&block)
      @node = AVLNode.from_items(items, lambda { |a,b| block.call(a) <=> block.call(b) })
    elsif block.arity == 2 || block.arity == -3
      items = items.sort(&block)
      SortedSet.uniq_by_comparator!(items, block)
      @node = AVLNode.from_items(items, block)
    else
      raise "Comparator block for Hamster::SortedSet must accept 1 or 2 arguments"
    end
  else
    @node = PlainAVLNode.from_items(items.uniq.sort!)
  end
end

Class Method Details

.[](*items) ⇒ SortedSet

Create a new SortedSet populated with the given items. This method does not accept a comparator block.

Returns:



61
62
63
# File 'lib/hamster/sorted_set.rb', line 61

def [](*items)
  new(items)
end

.emptySortedSet

Return an empty SortedSet. If used on a subclass, returns an empty instance of that class.

Returns:



69
70
71
# File 'lib/hamster/sorted_set.rb', line 69

def empty
  @empty ||= self.alloc(PlainAVLNode::EmptyNode)
end

Instance Method Details

#above(item) ⇒ SortedSet #above(item) {|item| ... } ⇒ nil

Select elements greater than a value.

Overloads:

  • #above(item) ⇒ SortedSet

    Return a new SortedSet containing all items greater than item.

    Examples:

    s = Hamster::SortedSet[2, 4, 6, 8, 10]
    s.above(6)
    # => Hamster::SortedSet[8, 10]

    Returns:

  • #above(item) {|item| ... } ⇒ nil

    Examples:

    s = Hamster::SortedSet[2, 4, 6, 8, 10]
    s.above(6) { |e| puts "Element: #{e}" }
    
    Element: 8
    Element: 10
    # => nil

    Yields:

    • (item)

      Once for each item greater than item, in order from lowest to highest.

    Returns:

    • (nil)

Parameters:

  • item (Object)


785
786
787
788
789
790
791
# File 'lib/hamster/sorted_set.rb', line 785

def above(item, &block)
  if block_given?
    @node.each_greater(item, false, &block)
  else
    self.class.alloc(@node.suffix(item, false))
  end
end

#add(item) ⇒ SortedSet Also known as: <<

Return a new SortedSet with item added. If item is already in the set, return self.

Examples:

Hamster::SortedSet["Dog", "Lion"].add("Elephant")
# => Hamster::SortedSet["Dog", "Elephant", "Lion"]

Parameters:

  • item (Object)

    The object to add

Returns:



153
154
155
156
157
158
159
# File 'lib/hamster/sorted_set.rb', line 153

def add(item)
  catch :present do
    node = @node.insert(item)
    return self.class.alloc(node)
  end
  self
end

#add?(item) ⇒ SortedSet, false

If item is not a member of this SortedSet, return a new SortedSet with item added. Otherwise, return false.

Examples:

Hamster::SortedSet["Dog", "Lion"].add?("Elephant")
# => Hamster::SortedSet["Dog", "Elephant", "Lion"]
Hamster::SortedSet["Dog", "Lion"].add?("Lion")
# => false

Parameters:

  • item (Object)

    The object to add

Returns:



173
174
175
# File 'lib/hamster/sorted_set.rb', line 173

def add?(item)
  !include?(item) && add(item)
end

#at(index) ⇒ Object

Retrieve the item at index. If there is none (either the provided index is too high or too low), return nil.

Examples:

s = Hamster::SortedSet["A", "B", "C", "D", "E", "F"]
s.at(2)   # => "C"
s.at(-2)  # => "E"
s.at(6)   # => nil

Parameters:

  • index (Integer)

    The index to retrieve

Returns:

  • (Object)


237
238
239
240
241
# File 'lib/hamster/sorted_set.rb', line 237

def at(index)
  index += @node.size if index < 0
  return nil if index >= @node.size || index < 0
  @node.at(index)
end

#below(item) ⇒ SortedSet #below(item) {|item| ... } ⇒ nil

Select elements less than a value.

Overloads:

  • #below(item) ⇒ SortedSet

    Return a new SortedSet containing all items less than item.

    Examples:

    s = Hamster::SortedSet[2, 4, 6, 8, 10]
    s.below(6)
    # => Hamster::SortedSet[2, 4]

    Returns:

  • #below(item) {|item| ... } ⇒ nil

    Examples:

    s = Hamster::SortedSet[2, 4, 6, 8, 10]
    s.below(6) { |e| puts "Element: #{e}" }
    
    Element: 2
    Element: 4
    # => nil

    Yields:

    • (item)

      Once for each item less than item, in order from lowest to highest.

    Returns:

    • (nil)

Parameters:

  • item (Object)


816
817
818
819
820
821
822
# File 'lib/hamster/sorted_set.rb', line 816

def below(item, &block)
  if block_given?
    @node.each_less(item, false, &block)
  else
    self.class.alloc(@node.prefix(item, false))
  end
end

#between(from, to) ⇒ SortedSet #between(item) {|item| ... } ⇒ nil

Select elements between two values.

Overloads:

  • #between(from, to) ⇒ SortedSet

    Return a new SortedSet containing all items less than or equal to to and greater than or equal to from.

    Examples:

    s = Hamster::SortedSet[2, 4, 6, 8, 10]
    s.between(5, 8)
    # => Hamster::SortedSet[6, 8]

    Returns:

  • #between(item) {|item| ... } ⇒ nil

    Examples:

    s = Hamster::SortedSet[2, 4, 6, 8, 10]
    s.between(5, 8) { |e| puts "Element: #{e}" }
    
    Element: 6
    Element: 8
    # => nil

    Yields:

    • (item)

      Once for each item less than or equal to to and greater than or equal to from, in order from lowest to highest.

    Returns:

    • (nil)

Parameters:

  • from (Object)
  • to (Object)


916
917
918
919
920
921
922
# File 'lib/hamster/sorted_set.rb', line 916

def between(from, to, &block)
  if block_given?
    @node.each_between(from, to, &block)
  else
    self.class.alloc(@node.between(from, to))
  end
end

#clearSortedSet

Return an empty SortedSet instance, of the same class as this one. Useful if you have multiple subclasses of SortedSet and want to treat them polymorphically.

Returns:



938
939
940
941
942
943
944
# File 'lib/hamster/sorted_set.rb', line 938

def clear
  if @node.natural_order?
    self.class.empty
  else
    self.class.alloc(@node.clear)
  end
end

#delete(item) ⇒ SortedSet

Return a new SortedSet with item removed. If item is not a member of the set, return self.

Examples:

Hamster::SortedSet["A", "B", "C"].delete("B")
# => Hamster::SortedSet["A", "C"]

Parameters:

  • item (Object)

    The object to remove

Returns:



186
187
188
189
190
191
192
193
194
195
196
# File 'lib/hamster/sorted_set.rb', line 186

def delete(item)
  catch :not_present do
    node = @node.delete(item)
    if node.empty? && node.natural_order?
      return self.class.empty
    else
      return self.class.alloc(node)
    end
  end
  self
end

#delete?(item) ⇒ SortedSet, false

If item is a member of this SortedSet, return a new SortedSet with item removed. Otherwise, return false.

Examples:

Hamster::SortedSet["A", "B", "C"].delete?("B")
# => Hamster::SortedSet["A", "C"]
Hamster::SortedSet["A", "B", "C"].delete?("Z")
# => false

Parameters:

  • item (Object)

    The object to remove

Returns:



209
210
211
# File 'lib/hamster/sorted_set.rb', line 209

def delete?(item)
  include?(item) && delete(item)
end

#delete_at(index) ⇒ SortedSet

Return a new SortedSet with the item at index removed. If the given index does not exist (if it is too high or too low), return self.

Examples:

Hamster::SortedSet["A", "B", "C", "D"].delete_at(2)
# => Hamster::SortedSet["A", "B", "D"]

Parameters:

  • index (Integer)

    The index to remove

Returns:



222
223
224
# File 'lib/hamster/sorted_set.rb', line 222

def delete_at(index)
  (item = at(index)) ? delete(item) : self
end

#difference(other) ⇒ SortedSet Also known as: subtract, -

Return a new SortedSet with all the items in other removed. other can be any Enumerable object.

Examples:

Hamster::SortedSet[1, 2] - Hamster::SortedSet[2, 3]
# => Hamster::SortedSet[1]

Parameters:

  • other (Enumerable)

    The collection to subtract from this set

Returns:



662
663
664
# File 'lib/hamster/sorted_set.rb', line 662

def difference(other)
  self.class.alloc(@node.bulk_delete(other))
end

#disjoint?(other) ⇒ Boolean

Return true if this set and other do not share any items.

Examples:

Hamster::SortedSet[1, 2].disjoint?(Hamster::SortedSet[3, 4])  # => true

Parameters:

Returns:

  • (Boolean)


739
740
741
742
743
744
745
746
# File 'lib/hamster/sorted_set.rb', line 739

def disjoint?(other)
  if size < other.size
    each { |item| return false if other.include?(item) }
  else
    other.each { |item| return false if include?(item) }
  end
  true
end

#drop(n) ⇒ SortedSet

Drop the first n elements and return the rest in a new SortedSet.

Examples:

Hamster::SortedSet["A", "B", "C", "D", "E", "F"].drop(2)
# => Hamster::SortedSet["C", "D", "E", "F"]

Parameters:

  • n (Integer)

    The number of elements to remove

Returns:



567
568
569
# File 'lib/hamster/sorted_set.rb', line 567

def drop(n)
  derive_new_sorted_set(@node.drop(n))
end

#drop_while {|item| ... } ⇒ SortedSet, Enumerator

Drop elements up to, but not including, the first element for which the block returns nil or false. Gather the remaining elements into a new SortedSet. If no block is given, an Enumerator is returned instead.

Examples:

Hamster::SortedSet[2, 4, 6, 7, 8, 9].drop_while { |e| e.even? }
# => Hamster::SortedSet[7, 8, 9]

Yields:

  • (item)

Returns:



593
594
595
596
597
598
599
600
601
# File 'lib/hamster/sorted_set.rb', line 593

def drop_while
  return enum_for(:drop_while) if not block_given?
  n = 0
  each do |item|
    break unless yield item
    n += 1
  end
  drop(n)
end

#each {|item| ... } ⇒ self, Enumerator

Call the given block once for each item in the set, passing each item from first to last successively to the block. If no block is provided, returns an Enumerator.

Examples:

Hamster::SortedSet["A", "B", "C"].each { |e| puts "Element: #{e}" }

Element: A
Element: B
Element: C
# => Hamster::SortedSet["A", "B", "C"]

Yields:

  • (item)

Returns:

  • (self, Enumerator)


382
383
384
385
386
# File 'lib/hamster/sorted_set.rb', line 382

def each(&block)
  return @node.to_enum if not block_given?
  @node.each(&block)
  self
end

#empty?Boolean

Return true if this SortedSet contains no items.

Returns:

  • (Boolean)


129
130
131
# File 'lib/hamster/sorted_set.rb', line 129

def empty?
  @node.empty?
end

#eql?(other) ⇒ Boolean

Return true if other has the same type and contents as this SortedSet.

Parameters:

  • other (Object)

    The object to compare with

Returns:

  • (Boolean)


950
951
952
953
954
955
956
957
958
959
960
# File 'lib/hamster/sorted_set.rb', line 950

def eql?(other)
  return true if other.equal?(self)
  return false if not instance_of?(other.class)
  return false if size != other.size
  a, b = self.to_enum, other.to_enum
  while true
    return false if !a.next.eql?(b.next)
  end
rescue StopIteration
  true
end

#exclusion(other) ⇒ SortedSet Also known as: ^

Return a new SortedSet with all the items which are members of this set or of other, but not both. other can be any Enumerable object.

Examples:

Hamster::SortedSet[1, 2] ^ Hamster::SortedSet[2, 3]
# => Hamster::SortedSet[1, 3]

Parameters:

  • other (Enumerable)

    The collection to take the exclusive disjunction of

Returns:



677
678
679
# File 'lib/hamster/sorted_set.rb', line 677

def exclusion(other)
  ((self | other) - (self & other))
end

#fetch(index) ⇒ Object #fetch(index) {|index| ... } ⇒ Object #fetch(index, default) ⇒ Object

Retrieve the value at index with optional default.

Overloads:

  • #fetch(index) ⇒ Object

    Retrieve the value at the given index, or raise an IndexError if not found.

    Examples:

    v = Hamster::SortedSet["A", "B", "C", "D"]
    v.fetch(2)       # => "C"
    v.fetch(-1)      # => "D"
    v.fetch(4)       # => IndexError: index 4 outside of vector bounds

    Parameters:

    • index (Integer)

      The index to look up

    Raises:

    • (IndexError)

      if index does not exist

  • #fetch(index) {|index| ... } ⇒ Object

    Retrieve the value at the given index, or return the result of yielding the block if not found.

    Examples:

    v = Hamster::SortedSet["A", "B", "C", "D"]
    v.fetch(2) { |i| i * i }   # => "C"
    v.fetch(4) { |i| i * i }   # => 16

    Parameters:

    • index (Integer)

      The index to look up

    Yields:

    • Once if the index is not found.

    Yield Parameters:

    • index (Integer)

      The index which does not exist

    Yield Returns:

    • (Object)

      Default value to return

  • #fetch(index, default) ⇒ Object

    Retrieve the value at the given index, or return the provided default value if not found.

    Examples:

    v = Hamster::SortedSet["A", "B", "C", "D"]
    v.fetch(2, "Z")  # => "C"
    v.fetch(4, "Z")  # => "Z"

    Parameters:

    • index (Integer)

      The index to look up

    • default (Object)

      Object to return if the key is not found

Returns:

  • (Object)


282
283
284
285
286
287
288
289
290
291
292
# File 'lib/hamster/sorted_set.rb', line 282

def fetch(index, default = (missing_default = true))
  if index >= -@node.size && index < @node.size
    at(index)
  elsif block_given?
    yield(index)
  elsif !missing_default
    default
  else
    raise IndexError, "index #{index} outside of sorted set bounds"
  end
end

#find_index(obj) ⇒ Integer #find_index {|element| ... } ⇒ Integer Also known as: index

Find the index of a given object or an element that satisfies the given block.

Overloads:

  • #find_index(obj) ⇒ Integer

    Return the index of the first object in this set which is equal to obj. Rather than using #==, we use #<=> (or our comparator block) for comparisons. This means we can find the index in O(log N) time, rather than O(N).

    Examples:

    s = Hamster::SortedSet[2, 4, 6, 8, 10]
    s.find_index(8)  # => 3

    Parameters:

    • obj (Object)

      The object to search for

  • #find_index {|element| ... } ⇒ Integer

    Return the index of the first object in this sorted set for which the block returns to true. This takes O(N) time.

    Examples:

    s = Hamster::SortedSet[2, 4, 6, 8, 10]
    s.find_index { |e| e > 7 }  # => 3

    Yields:

    • (element)

      An element in the sorted set

    Yield Returns:

    • (Boolean)

      True if this is element matches

Returns:

  • (Integer)

    The index of the object, or nil if not found.



535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
# File 'lib/hamster/sorted_set.rb', line 535

def find_index(obj = (missing_obj = true), &block)
  if !missing_obj
    # Enumerable provides a default implementation, but this is more efficient
    node = @node
    index = node.left.size
    while !node.empty?
      direction = node.direction(obj)
      if direction > 0
        node = node.right
        index += (node.left.size + 1)
      elsif direction < 0
        node = node.left
        index -= (node.right.size + 1)
      else
        return index
      end
    end
    nil
  else
    super(&block)
  end
end

#firstObject

Return the "lowest" element in this set, as determined by its sort order.

Returns:

  • (Object)


422
423
424
# File 'lib/hamster/sorted_set.rb', line 422

def first
  @node.min
end

#from(item) ⇒ SortedSet #from(item) {|item| ... } ⇒ nil

Select elements greater than or equal to a value.

Overloads:

  • #from(item) ⇒ SortedSet

    Return a new SortedSet containing all items greater than or equal item.

    Examples:

    s = Hamster::SortedSet[2, 4, 6, 8, 10]
    s.from(6)
    # => Hamster::SortedSet[6, 8, 10]

    Returns:

  • #from(item) {|item| ... } ⇒ nil

    Examples:

    s = Hamster::SortedSet[2, 4, 6, 8, 10]
    s.from(6) { |e| puts "Element: #{e}" }
    
    Element: 6
    Element: 8
    Element: 10
    # => nil

    Yields:

    • (item)

      Once for each item greater than or equal to item, in order from lowest to highest.

    Returns:

    • (nil)

Parameters:

  • item (Object)


848
849
850
851
852
853
854
# File 'lib/hamster/sorted_set.rb', line 848

def from(item, &block)
  if block_given?
    @node.each_greater(item, true, &block)
  else
    self.class.alloc(@node.suffix(item, true))
  end
end

#hashInteger

See Object#hash.

Returns:

  • (Integer)


964
965
966
# File 'lib/hamster/sorted_set.rb', line 964

def hash
  reduce(0) { |hash, item| (hash << 5) - hash + item.hash }
end

#include?(item) ⇒ Boolean Also known as: member?

Return true if the given item is present in this SortedSet. More precisely, return true if an object which compares as "equal" using this set's comparator is present.

Examples:

Hamster::SortedSet["A", "B", "C"].include?("B")  # => true

Parameters:

  • item (Object)

    The object to check for

Returns:

  • (Boolean)


489
490
491
# File 'lib/hamster/sorted_set.rb', line 489

def include?(item)
  @node.include?(item)
end

#intersect?(other) ⇒ Boolean

Return true if this set and other have at least one item in common.

Examples:

Hamster::SortedSet[1, 2].intersect?(Hamster::SortedSet[2, 3])  # => true

Parameters:

Returns:

  • (Boolean)


755
756
757
# File 'lib/hamster/sorted_set.rb', line 755

def intersect?(other)
  !disjoint?(other)
end

#intersection(other) ⇒ SortedSet Also known as: &

Return a new SortedSet which contains all the items which are members of both this set and other. other can be any Enumerable object.

Examples:

Hamster::SortedSet[1, 2] & Hamster::SortedSet[2, 3]
# => Hamster::SortedSet[2]

Parameters:

  • other (Enumerable)

    The collection to intersect with

Returns:



648
649
650
# File 'lib/hamster/sorted_set.rb', line 648

def intersection(other)
  self.class.alloc(@node.keep_only(other))
end

#lastObject

Return the "highest" element in this set, as determined by its sort order.

Returns:

  • (Object)


441
442
443
# File 'lib/hamster/sorted_set.rb', line 441

def last
  @node.max
end

#map {|item| ... } ⇒ SortedSet, Enumerator Also known as: collect

Invoke the given block once for each item in the set, and return a new SortedSet containing the values returned by the block. If no block is given, returns an Enumerator.

Examples:

Hamster::SortedSet[1, 2, 3].map { |e| -(e * e) }
# => Hamster::SortedSet[-9, -4, -1]

Yields:

  • (item)

    Once for each item.

Returns:



473
474
475
476
477
# File 'lib/hamster/sorted_set.rb', line 473

def map
  return enum_for(:map) if not block_given?
  return self if empty?
  self.class.alloc(@node.from_items(super))
end

#max {|a, b| ... } ⇒ Object

Return the "highest" element in this set, as determined by its sort order. Or, if a block is provided, use the block as a comparator to find the "highest" element. (See Enumerable#max.)

Examples:

Hamster::SortedSet["A", "B", "C"].max  # => "C"

Yields:

  • (a, b)

    Any number of times with different pairs of elements.

Returns:

  • (Object)


435
436
437
# File 'lib/hamster/sorted_set.rb', line 435

def max
  block_given? ? super : @node.max
end

#min {|a, b| ... } ⇒ Object

Return the "lowest" element in this set, as determined by its sort order. Or, if a block is provided, use the block as a comparator to find the "lowest" element. (See Enumerable#min.)

Examples:

Hamster::SortedSet["A", "B", "C"].min  # => "A"

Yields:

  • (a, b)

    Any number of times with different pairs of elements.

Returns:

  • (Object)


416
417
418
# File 'lib/hamster/sorted_set.rb', line 416

def min
  block_given? ? super : @node.min
end

#proper_subset?(other) ⇒ Boolean

Returns true if other contains all the items in this set, plus at least one item which is not in this set.

Examples:

Hamster::SortedSet[2, 3].proper_subset?(Hamster::SortedSet[1, 2, 3])     # => true
Hamster::SortedSet[1, 2, 3].proper_subset?(Hamster::SortedSet[1, 2, 3])  # => false

Parameters:

Returns:

  • (Boolean)


714
715
716
717
# File 'lib/hamster/sorted_set.rb', line 714

def proper_subset?(other)
  return false if other.size <= size
  all? { |item| other.include?(item) }
end

#proper_superset?(other) ⇒ Boolean

Returns true if this set contains all the items in other, plus at least one item which is not in other.

Examples:

Hamster::SortedSet[1, 2, 3].proper_superset?(Hamster::SortedSet[2, 3])     # => true
Hamster::SortedSet[1, 2, 3].proper_superset?(Hamster::SortedSet[1, 2, 3])  # => false

Parameters:

Returns:

  • (Boolean)


728
729
730
# File 'lib/hamster/sorted_set.rb', line 728

def proper_superset?(other)
  other.proper_subset?(self)
end

#reverse_each(&block) ⇒ self

Call the given block once for each item in the set, passing each item starting from the last, and counting back to the first, successively to the block.

Examples:

Hamster::SortedSet["A", "B", "C"].reverse_each { |e| puts "Element: #{e}" }

Element: C
Element: B
Element: A
# => Hamster::SortedSet["A", "B", "C"]

Returns:

  • (self)


401
402
403
404
405
# File 'lib/hamster/sorted_set.rb', line 401

def reverse_each(&block)
  return @node.enum_for(:reverse_each) if not block_given?
  @node.reverse_each(&block)
  self
end

#sampleObject

Return a randomly chosen item from this set. If the set is empty, return nil.

Examples:

Hamster::SortedSet[1, 2, 3, 4, 5].sample  # => 2

Returns:

  • (Object)


930
931
932
# File 'lib/hamster/sorted_set.rb', line 930

def sample
  @node.at(rand(@node.size))
end

#select {|item| ... } ⇒ SortedSet Also known as: find_all, keep_if

Return a new SortedSet containing all elements for which the given block returns true.

Examples:

Hamster::SortedSet["Bird", "Cow", "Elephant"].select { |e| e.size >= 4 }
# => Hamster::SortedSet["Bird", "Elephant"]

Yields:

  • (item)

    Once for each item.

Returns:



454
455
456
457
458
459
# File 'lib/hamster/sorted_set.rb', line 454

def select
  return enum_for(:select) unless block_given?
  items_to_delete = []
  each { |item| items_to_delete << item unless yield(item) }
  derive_new_sorted_set(@node.bulk_delete(items_to_delete))
end

#sizeInteger Also known as: length

Return the number of items in this SortedSet.

Examples:

Hamster::SortedSet["A", "B", "C"].size  # => 3

Returns:

  • (Integer)


139
140
141
# File 'lib/hamster/sorted_set.rb', line 139

def size
  @node.size
end

#set.slice(index) ⇒ Object #set.slice(index, length) ⇒ SortedSet #set.slice(index..end) ⇒ SortedSet Also known as: []

Return specific objects from the Vector. All overloads return nil if the starting index is out of range.

Overloads:

  • #set.slice(index) ⇒ Object

    Returns a single object at the given index. If index is negative, count backwards from the end.

    Examples:

    s = Hamster::SortedSet["A", "B", "C", "D", "E", "F"]
    s[2]  # => "C"
    s[-1] # => "F"
    s[6]  # => nil

    Parameters:

    • index (Integer)

      The index to retrieve. May be negative.

    Returns:

    • (Object)
  • #set.slice(index, length) ⇒ SortedSet

    Return a subset starting at index and continuing for length elements or until the end of the SortedSet, whichever occurs first.

    Examples:

    s = Hamster::SortedSet["A", "B", "C", "D", "E", "F"]
    s[2, 3]  # => Hamster::SortedSet["C", "D", "E"]
    s[-2, 3] # => Hamster::SortedSet["E", "F"]
    s[20, 1] # => nil

    Parameters:

    • start (Integer)

      The index to start retrieving items from. May be negative.

    • length (Integer)

      The number of items to retrieve.

    Returns:

  • #set.slice(index..end) ⇒ SortedSet

    Return a subset starting at index and continuing to index end or the end of the SortedSet, whichever occurs first.

    Examples:

    s = Hamster::SortedSet["A", "B", "C", "D", "E", "F"]
    s[2..3]    # => Hamster::SortedSet["C", "D"]
    s[-2..100] # => Hamster::SortedSet["E", "F"]
    s[20..21]  # => nil

    Parameters:

    • range (Range)

      The range of indices to retrieve.

    Returns:



334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
# File 'lib/hamster/sorted_set.rb', line 334

def slice(arg, length = (missing_length = true))
  if missing_length
    if arg.is_a?(Range)
      from, to = arg.begin, arg.end
      from += @node.size if from < 0
      to   += @node.size if to < 0
      to   += 1     if !arg.exclude_end?
      length = to - from
      length = 0 if length < 0
      subsequence(from, length)
    else
      at(arg)
    end
  else
    arg += @node.size if arg < 0
    subsequence(arg, length)
  end
end

#sort(&block) ⇒ SortedSet Also known as: sort_by

Return a new SortedSet with the same items, but a sort order determined by the given block.

Examples:

Hamster::SortedSet["Bird", "Cow", "Elephant"].sort { |a, b| a.size <=> b.size }
# => Hamster::SortedSet["Cow", "Bird", "Elephant"]
Hamster::SortedSet["Bird", "Cow", "Elephant"].sort_by { |e| e.size }
# => Hamster::SortedSet["Cow", "Bird", "Elephant"]

Returns:



504
505
506
507
508
509
510
# File 'lib/hamster/sorted_set.rb', line 504

def sort(&block)
  if block
    self.class.new(self.to_a, &block)
  else
    self.class.new(self.to_a.sort)
  end
end

#subset?(other) ⇒ Boolean

Return true if all items in this set are also in other.

Examples:

Hamster::SortedSet[2, 3].subset?(Hamster::SortedSet[1, 2, 3])  # => true

Parameters:

Returns:

  • (Boolean)


689
690
691
692
# File 'lib/hamster/sorted_set.rb', line 689

def subset?(other)
  return false if other.size < size
  all? { |item| other.include?(item) }
end

#superset?(other) ⇒ Boolean

Return true if all items in other are also in this set.

Examples:

Hamster::SortedSet[1, 2, 3].superset?(Hamster::SortedSet[2, 3])  # => true

Parameters:

Returns:

  • (Boolean)


701
702
703
# File 'lib/hamster/sorted_set.rb', line 701

def superset?(other)
  other.subset?(self)
end

#take(n) ⇒ SortedSet

Return only the first n elements in a new SortedSet.

Examples:

Hamster::SortedSet["A", "B", "C", "D", "E", "F"].take(4)
# => Hamster::SortedSet["A", "B", "C", "D"]

Parameters:

  • n (Integer)

    The number of elements to retain

Returns:



579
580
581
# File 'lib/hamster/sorted_set.rb', line 579

def take(n)
  derive_new_sorted_set(@node.take(n))
end

#take_while {|item| ... } ⇒ SortedSet, Enumerator

Gather elements up to, but not including, the first element for which the block returns nil or false, and return them in a new SortedSet. If no block is given, an Enumerator is returned instead.

Examples:

Hamster::SortedSet[2, 4, 6, 7, 8, 9].take_while { |e| e.even? }
# => Hamster::SortedSet[2, 4, 6]

Yields:

  • (item)

Returns:



613
614
615
616
617
618
619
620
621
# File 'lib/hamster/sorted_set.rb', line 613

def take_while
  return enum_for(:take_while) if not block_given?
  n = 0
  each do |item|
    break unless yield item
    n += 1
  end
  take(n)
end

#union(other) ⇒ SortedSet Also known as: |, +, merge

Return a new SortedSet which contains all the members of both this set and other. other can be any Enumerable object.

Examples:

Hamster::SortedSet[1, 2] | Hamster::SortedSet[2, 3]
# => Hamster::SortedSet[1, 2, 3]

Parameters:

  • other (Enumerable)

    The collection to merge with

Returns:



632
633
634
# File 'lib/hamster/sorted_set.rb', line 632

def union(other)
  self.class.alloc(@node.bulk_insert(other))
end

#up_to(item) ⇒ SortedSet #up_to(item) {|item| ... } ⇒ nil

Select elements less than or equal to a value.

Overloads:

  • #up_to(item) ⇒ SortedSet

    Return a new SortedSet containing all items less than or equal to item.

    Examples:

    s = Hamster::SortedSet[2, 4, 6, 8, 10]
    s.upto(6)
    # => Hamster::SortedSet[2, 4, 6]

    Returns:

  • #up_to(item) {|item| ... } ⇒ nil

    Examples:

    s = Hamster::SortedSet[2, 4, 6, 8, 10]
    s.up_to(6) { |e| puts "Element: #{e}" }
    
    Element: 2
    Element: 4
    Element: 6
    # => nil

    Yields:

    • (item)

      Once for each item less than or equal to item, in order from lowest to highest.

    Returns:

    • (nil)

Parameters:

  • item (Object)


882
883
884
885
886
887
888
# File 'lib/hamster/sorted_set.rb', line 882

def up_to(item, &block)
  if block_given?
    @node.each_less(item, true, &block)
  else
    self.class.alloc(@node.prefix(item, true))
  end
end

#values_at(*indices) ⇒ SortedSet

Return a new SortedSet with only the elements at the given indices. If any of the indices do not exist, they will be skipped.

Examples:

s = Hamster::SortedSet["A", "B", "C", "D", "E", "F"]
s.values_at(2, 4, 5)   # => Hamster::SortedSet["C", "E", "F"]

Parameters:

  • indices (Array)

    The indices to retrieve and gather into a new SortedSet

Returns:



363
364
365
366
# File 'lib/hamster/sorted_set.rb', line 363

def values_at(*indices)
  indices.select! { |i| i >= -@node.size && i < @node.size }
  self.class.new(indices.map! { |i| at(i) })
end