* [ruby-core:122842] [Ruby Feature#21518] Statistical helpers to `Enumerable`
@ 2025-07-23 15:30 Amitleshed (Amit Leshed) via ruby-core
2025-07-24 14:20 ` [ruby-core:122856] " Dan0042 (Daniel DeLorme) via ruby-core
` (11 more replies)
0 siblings, 12 replies; 13+ messages in thread
From: Amitleshed (Amit Leshed) via ruby-core @ 2025-07-23 15:30 UTC (permalink / raw)
To: ruby-core; +Cc: Amitleshed (Amit Leshed)
Issue #21518 has been reported by Amitleshed (Amit Leshed).
----------------------------------------
Feature #21518: Statistical helpers to `Enumerable`
https://bugs.ruby-lang.org/issues/21518
* Author: Amitleshed (Amit Leshed)
* Status: Open
----------------------------------------
**Summary**
I'd like to add two statistical helpers to `Enumerable`:
- `Enumerable#average` (arithmetic mean)
- `Enumerable#median`
Both are small, well-defined operations that many Rubyists re-implement in apps and gems. Providing them in core avoids repeated, ad-hoc code and aligns with `Enumerable#sum`, which Ruby already ships.
**Motivation**
- These are among the most common “roll-your-own” helpers for arrays/ranges of numbers.
- They are conceptually simple, universally useful beyond web/Rails.
- Similar to `sum`, they’re primitives for quick data analysis, ETL scripts, CLI tooling, etc.
- Including them encourages consistent semantics (what to do with empty sets, mixed numerics, etc.).
## Proposed API & Semantics
```ruby
Enumerable#average -> Float or nil
Enumerable#median -> Numeric or nil
```
```ruby
[1, 2, 3, 4].average # => 2.5
(1..4).average # => 2.5
[].average # => nil
[1, 3, 2].median # => 2
[1, 2, 3, 10].median # => 2.5
(1..6).median # => 3.5
[].median # => nil
```
Ruby implementation
```ruby
module Enumerable
def average
count = 0
total = 0.0
each do |x|
raise TypeError, "non-numeric value for average" unless x.is_a?(Numeric)
total += x
count += 1
end
count.zero? ? nil : total / count
end
def median
arr = to_a
return nil if arr.empty?
arr.each { |x| raise TypeError, "non-numeric value for median" unless x.is_a?(Numeric) }
arr.sort!
mid = arr.length / 2
arr.length.odd? ? arr[mid] : (arr[mid - 1] + arr[mid]) / 2.0
end
end
```
**Upon approval I'm more than willing to implement spec and code in C.**
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/
^ permalink raw reply [flat|nested] 13+ messages in thread
* [ruby-core:122856] [Ruby Feature#21518] Statistical helpers to `Enumerable`
2025-07-23 15:30 [ruby-core:122842] [Ruby Feature#21518] Statistical helpers to `Enumerable` Amitleshed (Amit Leshed) via ruby-core
@ 2025-07-24 14:20 ` Dan0042 (Daniel DeLorme) via ruby-core
2025-07-24 14:34 ` [ruby-core:122857] " Amitleshed (Amit Leshed) via ruby-core
` (10 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Dan0042 (Daniel DeLorme) via ruby-core @ 2025-07-24 14:20 UTC (permalink / raw)
To: ruby-core; +Cc: Dan0042 (Daniel DeLorme)
Issue #21518 has been updated by Dan0042 (Daniel DeLorme).
In favor, just careful about the bug in #median
```ruby
x = [1, 3, 2]
x.median #=> 2
x #=> [1, 2, 3] modified by #median
```
----------------------------------------
Feature #21518: Statistical helpers to `Enumerable`
https://bugs.ruby-lang.org/issues/21518#change-114147
* Author: Amitleshed (Amit Leshed)
* Status: Open
----------------------------------------
**Summary**
I'd like to add two statistical helpers to `Enumerable`:
- `Enumerable#average` (arithmetic mean)
- `Enumerable#median`
Both are small, well-defined operations that many Rubyists re-implement in apps and gems. Providing them in core avoids repeated, ad-hoc code and aligns with `Enumerable#sum`, which Ruby already ships.
**Motivation**
- These are among the most common “roll-your-own” helpers for arrays/ranges of numbers.
- They are conceptually simple, universally useful beyond web/Rails.
- Similar to `sum`, they’re primitives for quick data analysis, ETL scripts, CLI tooling, etc.
- Including them encourages consistent semantics (what to do with empty sets, mixed numerics, etc.).
## Proposed API & Semantics
```ruby
Enumerable#average -> Float or nil
Enumerable#median -> Numeric or nil
```
```ruby
[1, 2, 3, 4].average # => 2.5
(1..4).average # => 2.5
[].average # => nil
[1, 3, 2].median # => 2
[1, 2, 3, 10].median # => 2.5
(1..6).median # => 3.5
[].median # => nil
```
Ruby implementation
```ruby
module Enumerable
def average
count = 0
total = 0.0
each do |x|
raise TypeError, "non-numeric value for average" unless x.is_a?(Numeric)
total += x
count += 1
end
count.zero? ? nil : total / count
end
def median
arr = to_a
return nil if arr.empty?
arr.each { |x| raise TypeError, "non-numeric value for median" unless x.is_a?(Numeric) }
arr.sort!
mid = arr.length / 2
arr.length.odd? ? arr[mid] : (arr[mid - 1] + arr[mid]) / 2.0
end
end
```
**Upon approval I'm more than willing to implement spec and code in C.**
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/
^ permalink raw reply [flat|nested] 13+ messages in thread
* [ruby-core:122857] [Ruby Feature#21518] Statistical helpers to `Enumerable`
2025-07-23 15:30 [ruby-core:122842] [Ruby Feature#21518] Statistical helpers to `Enumerable` Amitleshed (Amit Leshed) via ruby-core
2025-07-24 14:20 ` [ruby-core:122856] " Dan0042 (Daniel DeLorme) via ruby-core
@ 2025-07-24 14:34 ` Amitleshed (Amit Leshed) via ruby-core
2025-07-24 14:35 ` [ruby-core:122858] " Amitleshed (Amit Leshed) via ruby-core
` (9 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Amitleshed (Amit Leshed) via ruby-core @ 2025-07-24 14:34 UTC (permalink / raw)
To: ruby-core; +Cc: Amitleshed (Amit Leshed)
Issue #21518 has been updated by Amitleshed (Amit Leshed).
Dan0042 (Daniel DeLorme) wrote in #note-1:
> In favor, just careful about the bug in #median
> ```ruby
> x = [1, 3, 2]
> x.median #=> 2
> x #=> [1, 2, 3] modified by #median
> ```
> You'll want to use `arr = entries` rather than `arr = to_a`
Right. Great catch.
Dan0042 (Daniel DeLorme) wrote in #note-1:
> In favor, just careful about the bug in #median
> ```ruby
> x = [1, 3, 2]
> x.median #=> 2
> x #=> [1, 2, 3] modified by #median
> ```
> You'll want to use `arr = entries` rather than `arr = to_a`
Thanks, great catch!
----------------------------------------
Feature #21518: Statistical helpers to `Enumerable`
https://bugs.ruby-lang.org/issues/21518#change-114148
* Author: Amitleshed (Amit Leshed)
* Status: Open
----------------------------------------
**Summary**
I'd like to add two statistical helpers to `Enumerable`:
- `Enumerable#average` (arithmetic mean)
- `Enumerable#median`
Both are small, well-defined operations that many Rubyists re-implement in apps and gems. Providing them in core avoids repeated, ad-hoc code and aligns with `Enumerable#sum`, which Ruby already ships.
**Motivation**
- These are among the most common “roll-your-own” helpers for arrays/ranges of numbers.
- They are conceptually simple, universally useful beyond web/Rails.
- Similar to `sum`, they’re primitives for quick data analysis, ETL scripts, CLI tooling, etc.
- Including them encourages consistent semantics (what to do with empty sets, mixed numerics, etc.).
## Proposed API & Semantics
```ruby
Enumerable#average -> Float or nil
Enumerable#median -> Numeric or nil
```
```ruby
[1, 2, 3, 4].average # => 2.5
(1..4).average # => 2.5
[].average # => nil
[1, 3, 2].median # => 2
[1, 2, 3, 10].median # => 2.5
(1..6).median # => 3.5
[].median # => nil
```
Ruby implementation
```ruby
module Enumerable
def average
count = 0
total = 0.0
each do |x|
raise TypeError, "non-numeric value for average" unless x.is_a?(Numeric)
total += x
count += 1
end
count.zero? ? nil : total / count
end
def median
arr = to_a
return nil if arr.empty?
arr.each { |x| raise TypeError, "non-numeric value for median" unless x.is_a?(Numeric) }
arr.sort!
mid = arr.length / 2
arr.length.odd? ? arr[mid] : (arr[mid - 1] + arr[mid]) / 2.0
end
end
```
**Upon approval I'm more than willing to implement spec and code in C.**
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/
^ permalink raw reply [flat|nested] 13+ messages in thread
* [ruby-core:122858] [Ruby Feature#21518] Statistical helpers to `Enumerable`
2025-07-23 15:30 [ruby-core:122842] [Ruby Feature#21518] Statistical helpers to `Enumerable` Amitleshed (Amit Leshed) via ruby-core
2025-07-24 14:20 ` [ruby-core:122856] " Dan0042 (Daniel DeLorme) via ruby-core
2025-07-24 14:34 ` [ruby-core:122857] " Amitleshed (Amit Leshed) via ruby-core
@ 2025-07-24 14:35 ` Amitleshed (Amit Leshed) via ruby-core
2025-07-25 15:54 ` [ruby-core:122864] " herwin (Herwin W) via ruby-core
` (8 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Amitleshed (Amit Leshed) via ruby-core @ 2025-07-24 14:35 UTC (permalink / raw)
To: ruby-core; +Cc: Amitleshed (Amit Leshed)
Issue #21518 has been updated by Amitleshed (Amit Leshed).
Thanks, great catch!
----------------------------------------
Feature #21518: Statistical helpers to `Enumerable`
https://bugs.ruby-lang.org/issues/21518#change-114149
* Author: Amitleshed (Amit Leshed)
* Status: Open
----------------------------------------
**Summary**
I'd like to add two statistical helpers to `Enumerable`:
- `Enumerable#average` (arithmetic mean)
- `Enumerable#median`
Both are small, well-defined operations that many Rubyists re-implement in apps and gems. Providing them in core avoids repeated, ad-hoc code and aligns with `Enumerable#sum`, which Ruby already ships.
**Motivation**
- These are among the most common “roll-your-own” helpers for arrays/ranges of numbers.
- They are conceptually simple, universally useful beyond web/Rails.
- Similar to `sum`, they’re primitives for quick data analysis, ETL scripts, CLI tooling, etc.
- Including them encourages consistent semantics (what to do with empty sets, mixed numerics, etc.).
## Proposed API & Semantics
```ruby
Enumerable#average -> Float or nil
Enumerable#median -> Numeric or nil
```
```ruby
[1, 2, 3, 4].average # => 2.5
(1..4).average # => 2.5
[].average # => nil
[1, 3, 2].median # => 2
[1, 2, 3, 10].median # => 2.5
(1..6).median # => 3.5
[].median # => nil
```
Ruby implementation
```ruby
module Enumerable
def average
count = 0
total = 0.0
each do |x|
raise TypeError, "non-numeric value for average" unless x.is_a?(Numeric)
total += x
count += 1
end
count.zero? ? nil : total / count
end
def median
arr = to_a
return nil if arr.empty?
arr.each { |x| raise TypeError, "non-numeric value for median" unless x.is_a?(Numeric) }
arr.sort!
mid = arr.length / 2
arr.length.odd? ? arr[mid] : (arr[mid - 1] + arr[mid]) / 2.0
end
end
```
**Upon approval I'm more than willing to implement spec and code in C.**
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/
^ permalink raw reply [flat|nested] 13+ messages in thread
* [ruby-core:122864] [Ruby Feature#21518] Statistical helpers to `Enumerable`
2025-07-23 15:30 [ruby-core:122842] [Ruby Feature#21518] Statistical helpers to `Enumerable` Amitleshed (Amit Leshed) via ruby-core
` (2 preceding siblings ...)
2025-07-24 14:35 ` [ruby-core:122858] " Amitleshed (Amit Leshed) via ruby-core
@ 2025-07-25 15:54 ` herwin (Herwin W) via ruby-core
2025-07-25 19:07 ` [ruby-core:122865] " Amitleshed (Amit Leshed) via ruby-core
` (7 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: herwin (Herwin W) via ruby-core @ 2025-07-25 15:54 UTC (permalink / raw)
To: ruby-core; +Cc: herwin (Herwin W)
Issue #21518 has been updated by herwin (Herwin W).
Ranges might need their own specialised implementation: this implementation will timeout on infinite ranges, and `(1..100000).average` (or `.median`) can be calculated without having to create an intermediate array. (Why anyone would want to calculate these values from this kind of Ranges is beyond me, but that's another issue)
----------------------------------------
Feature #21518: Statistical helpers to `Enumerable`
https://bugs.ruby-lang.org/issues/21518#change-114156
* Author: Amitleshed (Amit Leshed)
* Status: Open
----------------------------------------
**Summary**
I'd like to add two statistical helpers to `Enumerable`:
- `Enumerable#average` (arithmetic mean)
- `Enumerable#median`
Both are small, well-defined operations that many Rubyists re-implement in apps and gems. Providing them in core avoids repeated, ad-hoc code and aligns with `Enumerable#sum`, which Ruby already ships.
**Motivation**
- These are among the most common “roll-your-own” helpers for arrays/ranges of numbers.
- They are conceptually simple, universally useful beyond web/Rails.
- Similar to `sum`, they’re primitives for quick data analysis, ETL scripts, CLI tooling, etc.
- Including them encourages consistent semantics (what to do with empty sets, mixed numerics, etc.).
## Proposed API & Semantics
```ruby
Enumerable#average -> Float or nil
Enumerable#median -> Numeric or nil
```
```ruby
[1, 2, 3, 4].average # => 2.5
(1..4).average # => 2.5
[].average # => nil
[1, 3, 2].median # => 2
[1, 2, 3, 10].median # => 2.5
(1..6).median # => 3.5
[].median # => nil
```
Ruby implementation
```ruby
module Enumerable
def average
count = 0
total = 0.0
each do |x|
raise TypeError, "non-numeric value for average" unless x.is_a?(Numeric)
total += x
count += 1
end
count.zero? ? nil : total / count
end
def median
arr = to_a
return nil if arr.empty?
arr.each { |x| raise TypeError, "non-numeric value for median" unless x.is_a?(Numeric) }
arr.sort!
mid = arr.length / 2
arr.length.odd? ? arr[mid] : (arr[mid - 1] + arr[mid]) / 2.0
end
end
```
**Upon approval I'm more than willing to implement spec and code in C.**
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/
^ permalink raw reply [flat|nested] 13+ messages in thread
* [ruby-core:122865] [Ruby Feature#21518] Statistical helpers to `Enumerable`
2025-07-23 15:30 [ruby-core:122842] [Ruby Feature#21518] Statistical helpers to `Enumerable` Amitleshed (Amit Leshed) via ruby-core
` (3 preceding siblings ...)
2025-07-25 15:54 ` [ruby-core:122864] " herwin (Herwin W) via ruby-core
@ 2025-07-25 19:07 ` Amitleshed (Amit Leshed) via ruby-core
2025-07-25 20:08 ` [ruby-core:122866] " mame (Yusuke Endoh) via ruby-core
` (6 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Amitleshed (Amit Leshed) via ruby-core @ 2025-07-25 19:07 UTC (permalink / raw)
To: ruby-core; +Cc: Amitleshed (Amit Leshed)
Issue #21518 has been updated by Amitleshed (Amit Leshed).
***
Thanks for the engagement everyone
***
Here's a refactored version:
``` ruby
module Enumerable
def average
return nil if none?
return range_midpoint if numeric_range?
total = 0.0
count = 0
each do |x|
raise TypeError, "non-numeric value for average" unless x.is_a?(Numeric)
total += x
count += 1
end
total / count
end
def median
return nil if none?
return range_midpoint if numeric_range?
arr = entries
arr.each { |x| raise TypeError, "non-numeric value for median" unless x.is_a?(Numeric) }
arr.sort!
mid = arr.length / 2
arr.length.odd? ? arr[mid] : (arr[mid - 1] + arr[mid]) / 2.0
end
private
def numeric_range?
is_a?(Range) && first.is_a?(Numeric) && last.is_a?(Numeric)
end
def range_midpoint
max = exclude_end? ? (last - step) : last
(first + max) / 2.0
end
end
```
----------------------------------------
Feature #21518: Statistical helpers to `Enumerable`
https://bugs.ruby-lang.org/issues/21518#change-114157
* Author: Amitleshed (Amit Leshed)
* Status: Open
----------------------------------------
**Summary**
I'd like to add two statistical helpers to `Enumerable`:
- `Enumerable#average` (arithmetic mean)
- `Enumerable#median`
Both are small, well-defined operations that many Rubyists re-implement in apps and gems. Providing them in core avoids repeated, ad-hoc code and aligns with `Enumerable#sum`, which Ruby already ships.
**Motivation**
- These are among the most common “roll-your-own” helpers for arrays/ranges of numbers.
- They are conceptually simple, universally useful beyond web/Rails.
- Similar to `sum`, they’re primitives for quick data analysis, ETL scripts, CLI tooling, etc.
- Including them encourages consistent semantics (what to do with empty sets, mixed numerics, etc.).
## Proposed API & Semantics
```ruby
Enumerable#average -> Float or nil
Enumerable#median -> Numeric or nil
```
```ruby
[1, 2, 3, 4].average # => 2.5
(1..4).average # => 2.5
[].average # => nil
[1, 3, 2].median # => 2
[1, 2, 3, 10].median # => 2.5
(1..6).median # => 3.5
[].median # => nil
```
Ruby implementation
```ruby
module Enumerable
def average
count = 0
total = 0.0
each do |x|
raise TypeError, "non-numeric value for average" unless x.is_a?(Numeric)
total += x
count += 1
end
count.zero? ? nil : total / count
end
def median
arr = to_a
return nil if arr.empty?
arr.each { |x| raise TypeError, "non-numeric value for median" unless x.is_a?(Numeric) }
arr.sort!
mid = arr.length / 2
arr.length.odd? ? arr[mid] : (arr[mid - 1] + arr[mid]) / 2.0
end
end
```
**Upon approval I'm more than willing to implement spec and code in C.**
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/
^ permalink raw reply [flat|nested] 13+ messages in thread
* [ruby-core:122866] [Ruby Feature#21518] Statistical helpers to `Enumerable`
2025-07-23 15:30 [ruby-core:122842] [Ruby Feature#21518] Statistical helpers to `Enumerable` Amitleshed (Amit Leshed) via ruby-core
` (4 preceding siblings ...)
2025-07-25 19:07 ` [ruby-core:122865] " Amitleshed (Amit Leshed) via ruby-core
@ 2025-07-25 20:08 ` mame (Yusuke Endoh) via ruby-core
2025-07-31 15:23 ` [ruby-core:122890] " matheusrich (Matheus Richard) via ruby-core
` (5 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: mame (Yusuke Endoh) via ruby-core @ 2025-07-25 20:08 UTC (permalink / raw)
To: ruby-core; +Cc: mame (Yusuke Endoh)
Issue #21518 has been updated by mame (Yusuke Endoh).
Naturally, these methods have been desired by some people for a very long time, but Ruby has historically been very cautious about introducing them. Even the obviously useful `#sum` method was only added in 2016, which is relatively recent in Ruby's history.
One reason behind this caution is the reluctance to add methods to Array that assume all elements are Integer or Float. Since Array can contain Strings or other non-numeric objects, there's a question of whether it is appropriate to add methods that make no sense in such cases.
The reason why `#sum` was eventually added was the growing attention to an algorithm called the Kahan-Babuska Summation Algorithm. This is a clever algorithm that reduces floating-point error when summing, and it is actually implemented in `Array#sum`. Before this algorithm gained attention, I remember the prevailing opinion was that it should be written explicitly, like `ary.inject(0, &:+)`.
For now, you may want to try using https://github.com/red-data-tools/enumerable-statistics to get a better idea of what you actually need.
----------------------------------------
Feature #21518: Statistical helpers to `Enumerable`
https://bugs.ruby-lang.org/issues/21518#change-114167
* Author: Amitleshed (Amit Leshed)
* Status: Open
----------------------------------------
**Summary**
I'd like to add two statistical helpers to `Enumerable`:
- `Enumerable#average` (arithmetic mean)
- `Enumerable#median`
Both are small, well-defined operations that many Rubyists re-implement in apps and gems. Providing them in core avoids repeated, ad-hoc code and aligns with `Enumerable#sum`, which Ruby already ships.
**Motivation**
- These are among the most common “roll-your-own” helpers for arrays/ranges of numbers.
- They are conceptually simple, universally useful beyond web/Rails.
- Similar to `sum`, they’re primitives for quick data analysis, ETL scripts, CLI tooling, etc.
- Including them encourages consistent semantics (what to do with empty sets, mixed numerics, etc.).
## Proposed API & Semantics
```ruby
Enumerable#average -> Float or nil
Enumerable#median -> Numeric or nil
```
```ruby
[1, 2, 3, 4].average # => 2.5
(1..4).average # => 2.5
[].average # => nil
[1, 3, 2].median # => 2
[1, 2, 3, 10].median # => 2.5
(1..6).median # => 3.5
[].median # => nil
```
Ruby implementation
```ruby
module Enumerable
def average
count = 0
total = 0.0
each do |x|
raise TypeError, "non-numeric value for average" unless x.is_a?(Numeric)
total += x
count += 1
end
count.zero? ? nil : total / count
end
def median
arr = to_a
return nil if arr.empty?
arr.each { |x| raise TypeError, "non-numeric value for median" unless x.is_a?(Numeric) }
arr.sort!
mid = arr.length / 2
arr.length.odd? ? arr[mid] : (arr[mid - 1] + arr[mid]) / 2.0
end
end
```
**Upon approval I'm more than willing to implement spec and code in C.**
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/
^ permalink raw reply [flat|nested] 13+ messages in thread
* [ruby-core:122890] [Ruby Feature#21518] Statistical helpers to `Enumerable`
2025-07-23 15:30 [ruby-core:122842] [Ruby Feature#21518] Statistical helpers to `Enumerable` Amitleshed (Amit Leshed) via ruby-core
` (5 preceding siblings ...)
2025-07-25 20:08 ` [ruby-core:122866] " mame (Yusuke Endoh) via ruby-core
@ 2025-07-31 15:23 ` matheusrich (Matheus Richard) via ruby-core
2025-08-21 9:27 ` [ruby-core:123011] " matz (Yukihiro Matsumoto) via ruby-core
` (4 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: matheusrich (Matheus Richard) via ruby-core @ 2025-07-31 15:23 UTC (permalink / raw)
To: ruby-core; +Cc: matheusrich (Matheus Richard)
Issue #21518 has been updated by matheusrich (Matheus Richard).
I wonder if these helpers could be inside `Math::Statistics`:
```rb
Math::Statistics.average(some_enumerable)
```
I think it would be okay for this module to assume the arguments are numeric.
----------------------------------------
Feature #21518: Statistical helpers to `Enumerable`
https://bugs.ruby-lang.org/issues/21518#change-114191
* Author: Amitleshed (Amit Leshed)
* Status: Open
----------------------------------------
**Summary**
I'd like to add two statistical helpers to `Enumerable`:
- `Enumerable#average` (arithmetic mean)
- `Enumerable#median`
Both are small, well-defined operations that many Rubyists re-implement in apps and gems. Providing them in core avoids repeated, ad-hoc code and aligns with `Enumerable#sum`, which Ruby already ships.
**Motivation**
- These are among the most common “roll-your-own” helpers for arrays/ranges of numbers.
- They are conceptually simple, universally useful beyond web/Rails.
- Similar to `sum`, they’re primitives for quick data analysis, ETL scripts, CLI tooling, etc.
- Including them encourages consistent semantics (what to do with empty sets, mixed numerics, etc.).
## Proposed API & Semantics
```ruby
Enumerable#average -> Float or nil
Enumerable#median -> Numeric or nil
```
```ruby
[1, 2, 3, 4].average # => 2.5
(1..4).average # => 2.5
[].average # => nil
[1, 3, 2].median # => 2
[1, 2, 3, 10].median # => 2.5
(1..6).median # => 3.5
[].median # => nil
```
Ruby implementation
```ruby
module Enumerable
def average
count = 0
total = 0.0
each do |x|
raise TypeError, "non-numeric value for average" unless x.is_a?(Numeric)
total += x
count += 1
end
count.zero? ? nil : total / count
end
def median
arr = to_a
return nil if arr.empty?
arr.each { |x| raise TypeError, "non-numeric value for median" unless x.is_a?(Numeric) }
arr.sort!
mid = arr.length / 2
arr.length.odd? ? arr[mid] : (arr[mid - 1] + arr[mid]) / 2.0
end
end
```
**Upon approval I'm more than willing to implement spec and code in C.**
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/
^ permalink raw reply [flat|nested] 13+ messages in thread
* [ruby-core:123011] [Ruby Feature#21518] Statistical helpers to `Enumerable`
2025-07-23 15:30 [ruby-core:122842] [Ruby Feature#21518] Statistical helpers to `Enumerable` Amitleshed (Amit Leshed) via ruby-core
` (6 preceding siblings ...)
2025-07-31 15:23 ` [ruby-core:122890] " matheusrich (Matheus Richard) via ruby-core
@ 2025-08-21 9:27 ` matz (Yukihiro Matsumoto) via ruby-core
2025-08-22 5:00 ` [ruby-core:123046] " mrkn (Kenta Murata) via ruby-core
` (3 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: matz (Yukihiro Matsumoto) via ruby-core @ 2025-08-21 9:27 UTC (permalink / raw)
To: ruby-core; +Cc: matz (Yukihiro Matsumoto)
Issue #21518 has been updated by matz (Yukihiro Matsumoto).
I am positive about adding those methods, but I am no expert on Mathematics nor Statistics.
Matz.
----------------------------------------
Feature #21518: Statistical helpers to `Enumerable`
https://bugs.ruby-lang.org/issues/21518#change-114313
* Author: Amitleshed (Amit Leshed)
* Status: Open
----------------------------------------
**Summary**
I'd like to add two statistical helpers to `Enumerable`:
- `Enumerable#average` (arithmetic mean)
- `Enumerable#median`
Both are small, well-defined operations that many Rubyists re-implement in apps and gems. Providing them in core avoids repeated, ad-hoc code and aligns with `Enumerable#sum`, which Ruby already ships.
**Motivation**
- These are among the most common “roll-your-own” helpers for arrays/ranges of numbers.
- They are conceptually simple, universally useful beyond web/Rails.
- Similar to `sum`, they’re primitives for quick data analysis, ETL scripts, CLI tooling, etc.
- Including them encourages consistent semantics (what to do with empty sets, mixed numerics, etc.).
## Proposed API & Semantics
```ruby
Enumerable#average -> Float or nil
Enumerable#median -> Numeric or nil
```
```ruby
[1, 2, 3, 4].average # => 2.5
(1..4).average # => 2.5
[].average # => nil
[1, 3, 2].median # => 2
[1, 2, 3, 10].median # => 2.5
(1..6).median # => 3.5
[].median # => nil
```
Ruby implementation
```ruby
module Enumerable
def average
count = 0
total = 0.0
each do |x|
raise TypeError, "non-numeric value for average" unless x.is_a?(Numeric)
total += x
count += 1
end
count.zero? ? nil : total / count
end
def median
arr = to_a
return nil if arr.empty?
arr.each { |x| raise TypeError, "non-numeric value for median" unless x.is_a?(Numeric) }
arr.sort!
mid = arr.length / 2
arr.length.odd? ? arr[mid] : (arr[mid - 1] + arr[mid]) / 2.0
end
end
```
**Upon approval I'm more than willing to implement spec and code in C.**
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/
^ permalink raw reply [flat|nested] 13+ messages in thread
* [ruby-core:123046] [Ruby Feature#21518] Statistical helpers to `Enumerable`
2025-07-23 15:30 [ruby-core:122842] [Ruby Feature#21518] Statistical helpers to `Enumerable` Amitleshed (Amit Leshed) via ruby-core
` (7 preceding siblings ...)
2025-08-21 9:27 ` [ruby-core:123011] " matz (Yukihiro Matsumoto) via ruby-core
@ 2025-08-22 5:00 ` mrkn (Kenta Murata) via ruby-core
2025-08-22 15:15 ` [ruby-core:123054] " matheusrich (Matheus Richard) via ruby-core
` (2 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: mrkn (Kenta Murata) via ruby-core @ 2025-08-22 5:00 UTC (permalink / raw)
To: ruby-core; +Cc: mrkn (Kenta Murata)
Issue #21518 has been updated by mrkn (Kenta Murata).
Hi. I'm a creator of enumerable-statistics gem and the original proposer of `Array#sum` and `Enumerable#sum`.
In general, adding only `mean` (I prefer `mean` over `average`, see below) and `median` won't cover real-world statistical needs. When a sample mean is required, variance or standard deviation usually follow; where a sample median is used, quantiles or percentiles typically follow. Truly “median-only” scenarios are rare in my experience.
If these are added to core, we should set a high bar: numerically stable, one-pass algorithms with a C implementation for performance; and for median/percentiles computations, avoid full sort in favor of selection algorithms such as quickselect.
The enumerable-statistics gem already provides a simple one-pass combined methods such as `mean_variance` and `mean_stdev`. `median` and `percentile` for Enumerable remain to be implemented.
On naming: I strongly prefer `mean` over `average` for consistency with other programming languages and libraries (cf. #18057 note-8). Across Python/NumPy/Pandas, R, Julia, MATLAB, and so on,—`mean` is the standard term and API name. Aligning with that convention keeps Ruby familiar to users who work across stacks (acknowledging that a few general-purpose APIs, e.g., LINQ, use average).
----------------------------------------
Feature #21518: Statistical helpers to `Enumerable`
https://bugs.ruby-lang.org/issues/21518#change-114363
* Author: Amitleshed (Amit Leshed)
* Status: Open
----------------------------------------
**Summary**
I'd like to add two statistical helpers to `Enumerable`:
- `Enumerable#average` (arithmetic mean)
- `Enumerable#median`
Both are small, well-defined operations that many Rubyists re-implement in apps and gems. Providing them in core avoids repeated, ad-hoc code and aligns with `Enumerable#sum`, which Ruby already ships.
**Motivation**
- These are among the most common “roll-your-own” helpers for arrays/ranges of numbers.
- They are conceptually simple, universally useful beyond web/Rails.
- Similar to `sum`, they’re primitives for quick data analysis, ETL scripts, CLI tooling, etc.
- Including them encourages consistent semantics (what to do with empty sets, mixed numerics, etc.).
## Proposed API & Semantics
```ruby
Enumerable#average -> Float or nil
Enumerable#median -> Numeric or nil
```
```ruby
[1, 2, 3, 4].average # => 2.5
(1..4).average # => 2.5
[].average # => nil
[1, 3, 2].median # => 2
[1, 2, 3, 10].median # => 2.5
(1..6).median # => 3.5
[].median # => nil
```
Ruby implementation
```ruby
module Enumerable
def average
count = 0
total = 0.0
each do |x|
raise TypeError, "non-numeric value for average" unless x.is_a?(Numeric)
total += x
count += 1
end
count.zero? ? nil : total / count
end
def median
arr = to_a
return nil if arr.empty?
arr.each { |x| raise TypeError, "non-numeric value for median" unless x.is_a?(Numeric) }
arr.sort!
mid = arr.length / 2
arr.length.odd? ? arr[mid] : (arr[mid - 1] + arr[mid]) / 2.0
end
end
```
**Upon approval I'm more than willing to implement spec and code in C.**
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/
^ permalink raw reply [flat|nested] 13+ messages in thread
* [ruby-core:123054] [Ruby Feature#21518] Statistical helpers to `Enumerable`
2025-07-23 15:30 [ruby-core:122842] [Ruby Feature#21518] Statistical helpers to `Enumerable` Amitleshed (Amit Leshed) via ruby-core
` (8 preceding siblings ...)
2025-08-22 5:00 ` [ruby-core:123046] " mrkn (Kenta Murata) via ruby-core
@ 2025-08-22 15:15 ` matheusrich (Matheus Richard) via ruby-core
2025-08-22 18:24 ` [ruby-core:123056] " Eregon (Benoit Daloze) via ruby-core
2026-02-07 19:17 ` [ruby-core:124710] " trinistr (Alexander Bulancov) via ruby-core
11 siblings, 0 replies; 13+ messages in thread
From: matheusrich (Matheus Richard) via ruby-core @ 2025-08-22 15:15 UTC (permalink / raw)
To: ruby-core; +Cc: matheusrich (Matheus Richard)
Issue #21518 has been updated by matheusrich (Matheus Richard).
An `average` alias would be nice, though.
----------------------------------------
Feature #21518: Statistical helpers to `Enumerable`
https://bugs.ruby-lang.org/issues/21518#change-114372
* Author: Amitleshed (Amit Leshed)
* Status: Open
----------------------------------------
**Summary**
I'd like to add two statistical helpers to `Enumerable`:
- `Enumerable#average` (arithmetic mean)
- `Enumerable#median`
Both are small, well-defined operations that many Rubyists re-implement in apps and gems. Providing them in core avoids repeated, ad-hoc code and aligns with `Enumerable#sum`, which Ruby already ships.
**Motivation**
- These are among the most common “roll-your-own” helpers for arrays/ranges of numbers.
- They are conceptually simple, universally useful beyond web/Rails.
- Similar to `sum`, they’re primitives for quick data analysis, ETL scripts, CLI tooling, etc.
- Including them encourages consistent semantics (what to do with empty sets, mixed numerics, etc.).
## Proposed API & Semantics
```ruby
Enumerable#average -> Float or nil
Enumerable#median -> Numeric or nil
```
```ruby
[1, 2, 3, 4].average # => 2.5
(1..4).average # => 2.5
[].average # => nil
[1, 3, 2].median # => 2
[1, 2, 3, 10].median # => 2.5
(1..6).median # => 3.5
[].median # => nil
```
Ruby implementation
```ruby
module Enumerable
def average
count = 0
total = 0.0
each do |x|
raise TypeError, "non-numeric value for average" unless x.is_a?(Numeric)
total += x
count += 1
end
count.zero? ? nil : total / count
end
def median
arr = to_a
return nil if arr.empty?
arr.each { |x| raise TypeError, "non-numeric value for median" unless x.is_a?(Numeric) }
arr.sort!
mid = arr.length / 2
arr.length.odd? ? arr[mid] : (arr[mid - 1] + arr[mid]) / 2.0
end
end
```
**Upon approval I'm more than willing to implement spec and code in C.**
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/
^ permalink raw reply [flat|nested] 13+ messages in thread
* [ruby-core:123056] [Ruby Feature#21518] Statistical helpers to `Enumerable`
2025-07-23 15:30 [ruby-core:122842] [Ruby Feature#21518] Statistical helpers to `Enumerable` Amitleshed (Amit Leshed) via ruby-core
` (9 preceding siblings ...)
2025-08-22 15:15 ` [ruby-core:123054] " matheusrich (Matheus Richard) via ruby-core
@ 2025-08-22 18:24 ` Eregon (Benoit Daloze) via ruby-core
2026-02-07 19:17 ` [ruby-core:124710] " trinistr (Alexander Bulancov) via ruby-core
11 siblings, 0 replies; 13+ messages in thread
From: Eregon (Benoit Daloze) via ruby-core @ 2025-08-22 18:24 UTC (permalink / raw)
To: ruby-core; +Cc: Eregon (Benoit Daloze)
Issue #21518 has been updated by Eregon (Benoit Daloze).
mrkn (Kenta Murata) wrote in #note-12:
> In general, adding only `mean` (I prefer `mean` over `average`, see below) and `median` won't cover real-world statistical needs. When a sample mean is required, variance or standard deviation usually follow; where a sample median is used, quantiles or percentiles typically follow. Truly “median-only” scenarios are rare in my experience.
I think `mean` and `median` are frequently needed (at least I have reimplemented them many times) and would be worth adding to Array.
Not sure of the value to add them to Enumerable instead of Array (it would be much slower implemented on Enumerable).
I typically use the [median absolute deviation](https://en.wikipedia.org/wiki/Median_absolute_deviation) as a robust measure of the variability when using the median, and that can be trivially implemented on top of `#median`.
So for that case, only `median` is enough.
Regarding variance or standard deviation those are not robust and over-influenced by outliers, so I think it would make sense to not provide them, because they are often no longer recommended.
mrkn (Kenta Murata) wrote in #note-12:
> avoid full sort in favor of selection algorithms such as quickselect.
That seems one good reason to add it in core, the optimal algorithm is actually non-trivial and cannot easily be done in a Ruby one-liner for `median`.
`mean` is trivial but would still be nice to provide given it's so frequently used (also `data.sum / data.size.to_f` is not so pretty)).
Percentiles would be nice, especially if there is a more efficient algorithm for them than just sorting + indexing.
Percentiles are frequently useful e.g. to characterize response time/latency and also for boxplots. It's also a more robust way (e.g. with quartiles, so just 25 and 75 percentiles) to measure the variability than the standard deviation.
----------------------------------------
Feature #21518: Statistical helpers to `Enumerable`
https://bugs.ruby-lang.org/issues/21518#change-114374
* Author: Amitleshed (Amit Leshed)
* Status: Open
----------------------------------------
**Summary**
I'd like to add two statistical helpers to `Enumerable`:
- `Enumerable#average` (arithmetic mean)
- `Enumerable#median`
Both are small, well-defined operations that many Rubyists re-implement in apps and gems. Providing them in core avoids repeated, ad-hoc code and aligns with `Enumerable#sum`, which Ruby already ships.
**Motivation**
- These are among the most common “roll-your-own” helpers for arrays/ranges of numbers.
- They are conceptually simple, universally useful beyond web/Rails.
- Similar to `sum`, they’re primitives for quick data analysis, ETL scripts, CLI tooling, etc.
- Including them encourages consistent semantics (what to do with empty sets, mixed numerics, etc.).
## Proposed API & Semantics
```ruby
Enumerable#average -> Float or nil
Enumerable#median -> Numeric or nil
```
```ruby
[1, 2, 3, 4].average # => 2.5
(1..4).average # => 2.5
[].average # => nil
[1, 3, 2].median # => 2
[1, 2, 3, 10].median # => 2.5
(1..6).median # => 3.5
[].median # => nil
```
Ruby implementation
```ruby
module Enumerable
def average
count = 0
total = 0.0
each do |x|
raise TypeError, "non-numeric value for average" unless x.is_a?(Numeric)
total += x
count += 1
end
count.zero? ? nil : total / count
end
def median
arr = to_a
return nil if arr.empty?
arr.each { |x| raise TypeError, "non-numeric value for median" unless x.is_a?(Numeric) }
arr.sort!
mid = arr.length / 2
arr.length.odd? ? arr[mid] : (arr[mid - 1] + arr[mid]) / 2.0
end
end
```
**Upon approval I'm more than willing to implement spec and code in C.**
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/
^ permalink raw reply [flat|nested] 13+ messages in thread
* [ruby-core:124710] [Ruby Feature#21518] Statistical helpers to `Enumerable`
2025-07-23 15:30 [ruby-core:122842] [Ruby Feature#21518] Statistical helpers to `Enumerable` Amitleshed (Amit Leshed) via ruby-core
` (10 preceding siblings ...)
2025-08-22 18:24 ` [ruby-core:123056] " Eregon (Benoit Daloze) via ruby-core
@ 2026-02-07 19:17 ` trinistr (Alexander Bulancov) via ruby-core
11 siblings, 0 replies; 13+ messages in thread
From: trinistr (Alexander Bulancov) via ruby-core @ 2026-02-07 19:17 UTC (permalink / raw)
To: ruby-core; +Cc: trinistr (Alexander Bulancov)
Issue #21518 has been updated by trinistr (Alexander Bulancov).
> Percentiles would be nice, especially if there is a more efficient algorithm for them than just sorting + indexing.
It may be reasonable to implement percentiles without sorting, expecting the array to be pre-sorted, in the same way as `Array#bsearch` works. I think in most occasions of using percentiles, several values will be needed, and using some tricky algorithm will probably be more expensive than 1 sort + N fetches.
----------------------------------------
Feature #21518: Statistical helpers to `Enumerable`
https://bugs.ruby-lang.org/issues/21518#change-116307
* Author: Amitleshed (Amit Leshed)
* Status: Open
----------------------------------------
**Summary**
I'd like to add two statistical helpers to `Enumerable`:
- `Enumerable#average` (arithmetic mean)
- `Enumerable#median`
Both are small, well-defined operations that many Rubyists re-implement in apps and gems. Providing them in core avoids repeated, ad-hoc code and aligns with `Enumerable#sum`, which Ruby already ships.
**Motivation**
- These are among the most common “roll-your-own” helpers for arrays/ranges of numbers.
- They are conceptually simple, universally useful beyond web/Rails.
- Similar to `sum`, they’re primitives for quick data analysis, ETL scripts, CLI tooling, etc.
- Including them encourages consistent semantics (what to do with empty sets, mixed numerics, etc.).
## Proposed API & Semantics
```ruby
Enumerable#average -> Float or nil
Enumerable#median -> Numeric or nil
```
```ruby
[1, 2, 3, 4].average # => 2.5
(1..4).average # => 2.5
[].average # => nil
[1, 3, 2].median # => 2
[1, 2, 3, 10].median # => 2.5
(1..6).median # => 3.5
[].median # => nil
```
Ruby implementation
```ruby
module Enumerable
def average
count = 0
total = 0.0
each do |x|
raise TypeError, "non-numeric value for average" unless x.is_a?(Numeric)
total += x
count += 1
end
count.zero? ? nil : total / count
end
def median
arr = to_a
return nil if arr.empty?
arr.each { |x| raise TypeError, "non-numeric value for median" unless x.is_a?(Numeric) }
arr.sort!
mid = arr.length / 2
arr.length.odd? ? arr[mid] : (arr[mid - 1] + arr[mid]) / 2.0
end
end
```
**Upon approval I'm more than willing to implement spec and code in C.**
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-02-07 19:18 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-23 15:30 [ruby-core:122842] [Ruby Feature#21518] Statistical helpers to `Enumerable` Amitleshed (Amit Leshed) via ruby-core
2025-07-24 14:20 ` [ruby-core:122856] " Dan0042 (Daniel DeLorme) via ruby-core
2025-07-24 14:34 ` [ruby-core:122857] " Amitleshed (Amit Leshed) via ruby-core
2025-07-24 14:35 ` [ruby-core:122858] " Amitleshed (Amit Leshed) via ruby-core
2025-07-25 15:54 ` [ruby-core:122864] " herwin (Herwin W) via ruby-core
2025-07-25 19:07 ` [ruby-core:122865] " Amitleshed (Amit Leshed) via ruby-core
2025-07-25 20:08 ` [ruby-core:122866] " mame (Yusuke Endoh) via ruby-core
2025-07-31 15:23 ` [ruby-core:122890] " matheusrich (Matheus Richard) via ruby-core
2025-08-21 9:27 ` [ruby-core:123011] " matz (Yukihiro Matsumoto) via ruby-core
2025-08-22 5:00 ` [ruby-core:123046] " mrkn (Kenta Murata) via ruby-core
2025-08-22 15:15 ` [ruby-core:123054] " matheusrich (Matheus Richard) via ruby-core
2025-08-22 18:24 ` [ruby-core:123056] " Eregon (Benoit Daloze) via ruby-core
2026-02-07 19:17 ` [ruby-core:124710] " trinistr (Alexander Bulancov) via ruby-core
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).