philiprehberger-counter

Tests Gem Version Last updated

Frequency counter with most-common, merge, and percentage operations

Requirements

  • Ruby >= 3.1

Installation

Add to your Gemfile:

gem "philiprehberger-counter"

Or install directly:

gem install philiprehberger-counter

Usage

require "philiprehberger/counter"

counter = Philiprehberger::Counter.new(%w[a b a c a b])
counter['a']            # => 3
counter.most_common(2)  # => [["a", 3], ["b", 2]]
counter.total           # => 6
counter.percentage('a') # => 50.0

Increment

counter = Philiprehberger::Counter.new
counter.increment('x')
counter.increment('x', 5)
counter['x']  # => 6

Merge and Subtract

a = Philiprehberger::Counter.new(%w[x x y])
b = Philiprehberger::Counter.new(%w[x z])
merged = a.merge(b)
merged['x']  # => 3

Enumerable

counter = Philiprehberger::Counter.new(%w[a b a])
counter.map { |key, count| "#{key}: #{count}" }
# => ["a: 2", "b: 1"]

Decrement and Reset

counter = Philiprehberger::Counter.new(%w[a a a b])
counter.decrement('a')     # => 2
counter.decrement('a', 2)  # => 0
counter.reset('b')         # removes 'b'
counter.reset              # clears all

Batch Update

counter = Philiprehberger::Counter.new
counter.update(%w[x y x z])         # count from enumerable
counter.update({ 'x' => 10 })       # add from hash
counter['x']                         # => 12

Delete

counter = Philiprehberger::Counter.new(%w[a a b c])
counter.delete('a')  # => 2 (removes key entirely)
counter.delete('z')  # => nil (key not present)

Min and Max

counter = Philiprehberger::Counter.new(%w[a b a c a b])
counter.max_count  # => ["a", 3]
counter.min_count  # => ["c", 1]

JSON Serialization

counter = Philiprehberger::Counter.new(%w[a b a])
json = counter.to_json              # => '{"a":2,"b":1}'
restored = Philiprehberger::Counter.from_json(json)
restored['a']                        # => 2

Weighted Sampling

counter = Philiprehberger::Counter.new(%w[a a a b])
counter.sample      # => "a" (weighted by count)
counter.sample(3)   # => ["a", "a", "b"] (array of weighted samples)

Keys and Values

counter = Philiprehberger::Counter.new(%w[a b a])
counter.keys    # => ["a", "b"]
counter.values  # => [2, 1]

Filtering

counter = Philiprehberger::Counter.new(%w[a a a b b c])
frequent = counter.filter_by_count(min: 2)
frequent.to_h  # => {"a" => 3, "b" => 2}

Entropy

counter = Philiprehberger::Counter.new(%w[a b c d])
counter.entropy  # => 2.0 (uniform 4-key distribution, bits)

skewed = Philiprehberger::Counter.new(%w[a a a a b])
skewed.entropy   # => ~0.7219 (less than uniform upper bound)

API

Method Description
Counter.new(enumerable) Create a counter from an enumerable
#[key] Get count for a key
#increment(key, n) Increment count for a key
#most_common(n) Return n most common elements
#least_common(n) Return n least common elements
#total Sum of all counts
#merge(other) Merge two counters
#subtract(other) Subtract another counter
#percentage(key) Percentage of key relative to total
#decrement(key, n) Decrement count for a key, floored at zero
#reset(key) Reset a specific key or clear all counts
#update(data) Batch update from a Hash or Enumerable
#delete(key) Remove a key entirely, returns count or nil
#max_count Key-count pair with highest count
#min_count Key-count pair with lowest count
#to_json Serialize counter to JSON string
.from_json(str) Deserialize counter from JSON string
#sample(n) Weighted random sample based on counts
#keys Return all tracked keys
#values Return all count values
#filter_by_count(min:, max:) Filter entries by count range
#entropy Shannon entropy of the count distribution in bits
#to_h Convert to a plain hash
#size Number of unique keys

Development

bundle install
bundle exec rspec
bundle exec rubocop

Support

If you find this project useful:

Star the repo

🐛 Report issues

💡 Suggest features

❤️ Sponsor development

🌐 All Open Source Projects

💻 GitHub Profile

🔗 LinkedIn Profile

License

MIT