Module: Enumerable

Defined in:
lib/active_median/enumerable.rb

Instance Method Summary collapse

Instance Method Details

#median(*args, &block) ⇒ Object



3
4
5
6
7
8
9
10
11
12
# File 'lib/active_median/enumerable.rb', line 3

def median(*args, &block)
  if !block && respond_to?(:scoping)
    scoping { @klass.median(*args) }
  elsif !block && respond_to?(:with_scope)
    with_scope(self) { klass.median(*args) }
  else
    raise ArgumentError, "wrong number of arguments (given #{args.size}, expected 0)" if args.any?
    percentile(0.5, &block)
  end
end

#percentile(*args, &block) ⇒ Object



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/active_median/enumerable.rb', line 16

def percentile(*args, &block)
  if !block && respond_to?(:scoping)
    scoping { @klass.percentile(*args) }
  elsif !block && respond_to?(:with_scope)
    with_scope(self) { klass.percentile(*args) }
  else
    raise ArgumentError, "wrong number of arguments (given #{args.size}, expected 1)" if args.size != 1

    percentile = args[0].to_f
    raise ArgumentError, "percentile is not between 0 and 1" if percentile < 0 || percentile > 1

    # uses C=1 variant, like percentile_cont
    # https://en.wikipedia.org/wiki/Percentile#The_linear_interpolation_between_closest_ranks_method
    sorted = map(&block).sort
    x = percentile * (sorted.size - 1)
    r = x % 1
    i = x.floor
    if i == sorted.size - 1
      sorted[-1]
    else
      sorted[i] + r * (sorted[i + 1] - sorted[i])
    end
  end
end