😺
[Feature #21518] Enumerable に統計を扱うメソッドを追加する提案
[Feature #21518] Statistical helpers to Enumerable
-
Enumerableに統計を扱うメソッドを追加する提案 - このチケットだと
Enumerable#averageとEnumerable#medianの2つのメソッドを追加する提案がされている - 動作イメージは以下の通り
# Enumerable#average -> Float or nil
# Enumerable#median -> Numeric or nil
[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 はこのあたりのメソッドを追加するに慎重で
Enumerable#sumも比較的最近(2016年)追加された、というコメントがされていますね - 慎重になる背景としてはこれらのメソッドはすべての要素が
Float / Integerである前提となっており、そういうメソッドを追加することに抵抗があるみたい- 配列の要素が文字列や数値以外のオブジェクトの場合は意味のないメソッドになってしまうのでそういうメソッドを追加することが適切かどうか、みたいな問題がある
- このあたりは
Enumerable#sumも同じ課題があったみたいなんですが当時、和を計算する Kahan-Babuska Summation Algorithm というアルゴリズムが注目されていた、みたいな背景があったみたいですね- 浮動小数点の誤差を減らすアルゴリズムらしい
- カハンの加算アルゴリズム - Wikipedia
- 実際に単純に
Float値を加算した場合と#sumを利用した場合だと結果が異なるので#sumを利用する有用性があるみたいですね
ary = [1.12, 1.23, 1.34, 1.45, 1.56]
# 単純に Float 値を加算した場合は誤差が発生する
pp ary.inject(:+) # => 6.700000000000001
# こっちは誤差が出ずに正しい結果が取得できる
pp ary.sum # => 6.7
- 今回提案されている
#averageや#medianもこのあたりの有用性が説明できると入りやすかったりするんですかねー - また別の目線として
Math::Statisticsのクラスメソッドとして定義する案もコメントされていますね
Math::Statistics.average(some_enumerable)
- 確かにこっちのほうが適切な気もする
Discussion