philiprehberger-ring_buffer
Fixed-size circular buffer with overflow, statistics, and enumeration
Requirements
- Ruby >= 3.1
Installation
Add to your Gemfile:
gem "philiprehberger-ring_buffer"
Or install directly:
gem install philiprehberger-ring_buffer
Usage
require "philiprehberger/ring_buffer"
buf = Philiprehberger::RingBuffer.new(3)
buf.push(1)
buf.push(2)
buf.push(3)
buf.push(4) # overwrites 1
buf.to_a # => [2, 3, 4]
buf.full? # => true
Index Access
buf = Philiprehberger::RingBuffer.new(5)
[10, 20, 30].each { |v| buf.push(v) }
buf[0] # => 10 (oldest)
buf[-1] # => 30 (newest)
buf[99] # => nil (out of bounds)
First / Last Elements
buf = Philiprehberger::RingBuffer.new(10)
(1..10).each { |v| buf.push(v) }
buf.first # => 1
buf.first(3) # => [1, 2, 3]
buf.last(3) # => [8, 9, 10]
Clear
buf = Philiprehberger::RingBuffer.new(5)
[1, 2, 3].each { |v| buf.push(v) }
buf.clear
buf.size # => 0
buf.empty? # => true
Consuming Elements
buf = Philiprehberger::RingBuffer.new(3)
[1, 2, 3].each { |v| buf.push(v) }
buf.shift # => 1 (removes oldest)
buf.pop # => 3 (removes newest)
buf.to_a # => [2]
buf.push(4)
buf.push(5)
buf.oldest # => 2 (peek, no mutation)
buf.newest # => 5
shift, pop, oldest, and newest all return nil when the buffer is empty.
Statistics
buf = Philiprehberger::RingBuffer.new(100)
[10, 20, 30].each { |v| buf.push(v) }
buf.average # => 20.0
buf.sum # => 60
buf.min # => 10
buf.max # => 30
buf.variance # => 66.66666666666667
buf.stddev # => 8.16496580927726
buf.median # => 20.0
Resize
buf = Philiprehberger::RingBuffer.new(3)
[1, 2, 3].each { |v| buf.push(v) }
buf.resize(5)
buf.capacity # => 5
buf.to_a # => [1, 2, 3]
buf.resize(2)
buf.to_a # => [2, 3] (keeps most recent)
Batch Push
buf = Philiprehberger::RingBuffer.new(5)
buf.concat(1, 2, 3, 4, 5)
buf.to_a # => [1, 2, 3, 4, 5]
Percentile
buf = Philiprehberger::RingBuffer.new(100)
(1..100).each { |v| buf.push(v) }
buf.percentile(25) # => 25.75
buf.percentile(50) # => 50.5
buf.percentile(75) # => 75.25
buf.percentile(90) # => 90.1
Random Sampling
buf = Philiprehberger::RingBuffer.new(5)
[10, 20, 30, 40, 50].each { |v| buf.push(v) }
buf.sample # => random element
buf.sample(2) # => [random, random]
Enumerable
buf = Philiprehberger::RingBuffer.new(5)
[1, 2, 3].each { |v| buf.push(v) }
buf.map { |v| v * 2 } # => [2, 4, 6]
buf.select(&:odd?) # => [1, 3]
API
| Method | Description |
|---|---|
RingBuffer.new(capacity) |
Create a buffer with fixed capacity |
#push(value) |
Add a value, overwriting oldest if full |
#shift |
Remove and return the oldest element (or nil) |
#pop |
Remove and return the newest element (or nil) |
#oldest |
Peek the oldest element without removing (or nil) |
#newest |
Peek the newest element without removing (or nil) |
#[](index) |
Access by index (0 = oldest, -1 = newest) |
#to_a |
Convert to array (oldest first) |
#size |
Number of elements in the buffer |
#full? |
Whether the buffer is at capacity |
#empty? |
Whether the buffer has no elements |
#first(n) |
First n elements (oldest) |
#last(n) |
Last n elements (most recent) |
#clear |
Remove all elements, reset state |
#concat(*values) |
Push multiple values at once |
#resize(new_capacity) |
Change buffer capacity, keeping most recent elements |
#percentile(p) |
Calculate the p-th percentile (0-100) with interpolation |
#sample(n) |
Random element (or array of n random elements) |
#inspect |
Human-readable string representation |
#average |
Average of numeric elements |
#sum |
Sum of numeric elements |
#min |
Minimum element |
#max |
Maximum element |
#variance |
Population variance |
#stddev |
Population standard deviation |
#median |
Median value |
Development
bundle install
bundle exec rspec
bundle exec rubocop
Support
If you find this project useful: