Class: TopN

Inherits:
Hash
  • Object
show all
Defined in:
lib/top_n.rb

Overview

Note:

Note that while the number of keys is restricted, the values are not. This can cause memory issues if many values are added to the same key. If this is the type of data you are tracking, you may need a different solution.

This class tracks the top (or bottom) N values for a set of keys.

As keys and values are added, only the largest (or smallest) keys will be recorded. As larger (or smaller) keys are added, unneeded items are removed.

Keys may be any object that is comparable with < and >. Values may be any object, and are not processed beyond appending them to an internal list.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(default = nil, options = {}) ⇒ TopN

Create a new TopN object. Options available:

Examples:

Create with default options

topn = TopN.new

Create with a maximum size of 10, and track smaller values

topn = TopN.new(maxkeys: 10, direction: :bottom)

Parameters:

  • options (Hash) (defaults to: {})

    the options used to configure the TopN object.

Options Hash (options):

  • :maxkeys (Fixnum)

    The maximum number of keys to track. Must be a positive Fixnum. Defaults to 100.

  • :direction (Symbol)

    Configure the direction. If this is :top, the largest keys will be maintained. If :bottom, the smallest keys will be maintained. Any other value throws an exception. Defaults to :top.

Raises:

  • (ArgumentError)

    if an invalid value is detected for any option.



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/top_n.rb', line 56

def initialize(default = nil, options = {})
  options = {
    maxkeys: 100,
    direction: :top,
  }.merge(options)

  options.keys.each do |opt|
    unless [:maxkeys, :direction].include?opt
      raise ArgumentError.new("invalid option #{opt}")
    end
  end

  @maxkeys = options[:maxkeys]
  @direction = options[:direction]
  @threshold_key = nil

  unless [:top, :bottom].include?(@direction)
    raise ArgumentError.new("direction must be :top or :bottom")
  end

  unless @maxkeys.is_a?Fixnum
    raise ArgumentError.new("maxkeys must be a Fixnum")
  end

  if @maxkeys <= 0
    raise ArgumentError.new("maxkeys must be >= 1")
  end

  super(default)
end

Instance Attribute Details

#directionSymbol (readonly)

The configured direction.

Returns:

  • (Symbol)

    either :top or :bottom.



24
25
26
# File 'lib/top_n.rb', line 24

def direction
  @direction
end

#maxkeysFixnum (readonly)

The maxinum number of keys which will be tracked.

Returns:

  • (Fixnum)

    the configured maximum number of keys to be tracked.



20
21
22
# File 'lib/top_n.rb', line 20

def maxkeys
  @maxkeys
end

#threshold_keyObject (readonly)

The current value of the minimum (:top) or maximum (:bottom) key.

Returns:

  • (Object)

    the threshold key.



28
29
30
# File 'lib/top_n.rb', line 28

def threshold_key
  @threshold_key
end

Instance Method Details

#[]=(key, value) ⇒ Object

Behave like #store, with the same semantics.



122
123
124
# File 'lib/top_n.rb', line 122

def []=(key, value)
  store(key, value)
end

#store(key, value) ⇒ Object

Add a key, value pair.

If the key already exists, the value will be appended to the existing list of values at that key.

If an existing (key, value) is permitted, and will result in the list of values at that key having the same value multiple times.

the value is not added because there are too many keys already present.

Parameters:

  • key (Object)

    the key, which must be compariable with < and >.

  • value (Object)

    the value, which is added to the key’s list of values. Adding the same value to a key multiple times results in duplicate values being recorded.

Returns:

  • (Object)

    the value passed in. This will be returned even if



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/top_n.rb', line 103

def store(key, value)
  @threshold_key ||= key

  if has_key?key
    fetch(key) << value
  else
    if size >= @maxkeys
      return value if compare_to_threshold(key)
      delete(@threshold_key)
      adjust_threshold
    end
    super_store(key, [ value ])
    @threshold_key = key if compare_to_threshold(key)
  end

  value
end

#super_bracket_assignObject



31
# File 'lib/top_n.rb', line 31

alias_method :super_bracket_assign, :[]=

#super_storeObject



30
# File 'lib/top_n.rb', line 30

alias_method :super_store, :store