average 3.0 → 3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +32 -2
- data/lib/average.rb +1 -2
- data/lib/average/array_overrides.rb +10 -2
- data/lib/average/average_helper.rb +35 -32
- data/lib/average/mean.rb +6 -4
- data/lib/average/median.rb +19 -17
- data/lib/average/mode.rb +30 -17
- data/lib/average/version.rb +2 -2
- data/spec/array_overrides_spec.rb +9 -1
- data/spec/average_helper_spec.rb +2 -2
- data/spec/mode_spec.rb +23 -12
- metadata +2 -2
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
+
[](https://semaphoreci.com/fegoa89/average)
|
2
|
+
|
1
3
|
# Average
|
2
4
|
|
3
|
-
|
5
|
+
Simple gem to calculate mean, median and mode from an array.
|
4
6
|
|
5
7
|
## Installation
|
6
8
|
|
@@ -18,7 +20,35 @@ Or install it yourself as:
|
|
18
20
|
|
19
21
|
## Usage
|
20
22
|
|
21
|
-
|
23
|
+
Get Median
|
24
|
+
|
25
|
+
$ [3, 4, 5, 2, 3, 1].mean
|
26
|
+
$ 3.0
|
27
|
+
|
28
|
+
Get Mode
|
29
|
+
|
30
|
+
$ [2,4,6,14,21,24,229,24,24,39].mode
|
31
|
+
$ 24
|
32
|
+
|
33
|
+
It gives back an array due that could be possible to have more than one mode in a array
|
34
|
+
|
35
|
+
$ [1, 2, 2, 2, 3, 3, 7, 7, 7, 9].mode
|
36
|
+
$ [2, 7]
|
37
|
+
|
38
|
+
But if you want to have only a unique mode, you can use 'unique_mode' method (Only for Ruby versions bigger than 1.8.7 -> http://apidock.com/ruby/v1_8_7_72/Enumerable/max_by).
|
39
|
+
|
40
|
+
$ [1, 2, 2, 2, 3, 3, 7, 7, 7, 9].unique_mode
|
41
|
+
$ 2
|
42
|
+
|
43
|
+
Get Median
|
44
|
+
|
45
|
+
$ [3,4,5].median
|
46
|
+
$ 4
|
47
|
+
|
48
|
+
All methods described aboved can handle an array of integers, floats, strings or a mixed array with all of them
|
49
|
+
|
50
|
+
$ [3, "4", 5, 2.0, 3, "1.0"].mean
|
51
|
+
$ 3.0
|
22
52
|
|
23
53
|
## Contributing
|
24
54
|
|
data/lib/average.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
include Mean
|
2
|
+
include Mode
|
3
|
+
include Median
|
4
|
+
include AverageHelper
|
5
|
+
|
3
6
|
class Array
|
4
7
|
def mean
|
5
8
|
get_mean(self)
|
@@ -12,4 +15,9 @@ class Array
|
|
12
15
|
def median
|
13
16
|
get_median(self)
|
14
17
|
end
|
18
|
+
|
19
|
+
def unique_mode
|
20
|
+
get_unique_mode(self)
|
21
|
+
end
|
22
|
+
|
15
23
|
end
|
@@ -1,43 +1,46 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
1
|
+
module AverageHelper
|
2
|
+
def valid_array?(array)
|
3
|
+
# Valid if:
|
4
|
+
# - the class of the parameter 'array' respond to Array
|
5
|
+
# - the parameter 'Array' is not null or empty.
|
6
|
+
# - The array given contains Integers, Floats, and Strings that could be turned to a valid digit.
|
7
|
+
( array.is_a?(Array) && !array.nil? && !array.empty? && array_contain_digits?(array) )
|
8
|
+
end
|
8
9
|
|
9
|
-
def array_contain_digits?(array)
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
def array_contain_digits?(array)
|
11
|
+
# Go through all elements
|
12
|
+
result = true
|
13
|
+
array.each do |array_element|
|
14
|
+
if !value_can_be_handled?(array_element)
|
15
|
+
result = false
|
16
|
+
end
|
15
17
|
end
|
18
|
+
result
|
16
19
|
end
|
17
|
-
result
|
18
|
-
end
|
19
20
|
|
20
|
-
def value_can_be_handled?(element)
|
21
|
-
|
22
|
-
|
23
|
-
end
|
21
|
+
def value_can_be_handled?(element)
|
22
|
+
# Check if the elements of the array 'look like numbers'.
|
23
|
+
element.is_a?(Integer) || element.is_a?(Float) || looks_like_a_digit?(element)
|
24
|
+
end
|
24
25
|
|
25
26
|
|
26
|
-
def looks_like_a_digit?(digit)
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
27
|
+
def looks_like_a_digit?(digit)
|
28
|
+
if digit.is_a?(String) && digit !~ /^\s*[+-]?((\d+_?)*\d+(\.(\d+_?)*\d+)?|\.(\d+_?)*\d+)(\s*|([eE][+-]?(\d+_?)*\d+)\s*)$/
|
29
|
+
# is _not_ a string that could be turned to a digit
|
30
|
+
false
|
31
|
+
else
|
32
|
+
# is a string that could be a digit
|
33
|
+
true
|
34
|
+
end
|
33
35
|
end
|
34
|
-
end
|
35
36
|
|
36
|
-
def clean_array(array)
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
def clean_array(array)
|
38
|
+
array.each_with_index do |val, index|
|
39
|
+
if val.is_a?(String)
|
40
|
+
val.include?('.') ? (array[index] = val.to_f) : (array[index] = val.to_i)
|
41
|
+
end
|
40
42
|
end
|
43
|
+
array
|
41
44
|
end
|
42
|
-
|
45
|
+
|
43
46
|
end
|
data/lib/average/mean.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
module Mean
|
2
|
+
def get_mean(array)
|
3
|
+
if valid_array?(array)
|
4
|
+
clean_array(array).inject(0) { |sum, x| sum += x } / array.size.to_f
|
5
|
+
end
|
6
|
+
end
|
5
7
|
end
|
data/lib/average/median.rb
CHANGED
@@ -1,22 +1,24 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
end
|
1
|
+
module Median
|
2
|
+
def get_median(array)
|
3
|
+
if valid_array?(array)
|
4
|
+
calculate_median(clean_array(array))
|
5
|
+
end
|
6
|
+
end
|
6
7
|
|
7
|
-
def calculate_median(array)
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
def calculate_median(array)
|
9
|
+
array.sort!
|
10
|
+
if array.length.even?
|
11
|
+
get_mean( middle_items_to_average(array) )
|
12
|
+
else
|
13
|
+
array[ array.length / 2.to_f ]
|
14
|
+
end
|
13
15
|
end
|
14
|
-
end
|
15
16
|
|
16
|
-
def middle_item(array)
|
17
|
-
|
18
|
-
end
|
17
|
+
def middle_item(array)
|
18
|
+
array.size / 2
|
19
|
+
end
|
19
20
|
|
20
|
-
def middle_items_to_average(array)
|
21
|
-
|
21
|
+
def middle_items_to_average(array)
|
22
|
+
array[ middle_item(array) -1 .. middle_item(array) ]
|
23
|
+
end
|
22
24
|
end
|
data/lib/average/mode.rb
CHANGED
@@ -1,20 +1,33 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
module Mode
|
2
|
+
def get_mode(array)
|
3
|
+
if valid_array?(array)
|
4
|
+
result = repetition_hash( clean_array(array) )
|
5
|
+
if build_hash_result(result).count > 1
|
6
|
+
# It contains more than one mode
|
7
|
+
build_hash_result(result).keys.collect { |float| float.to_i }
|
8
|
+
else
|
9
|
+
# It contains only one mode
|
10
|
+
build_hash_result(result).keys.first
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
7
14
|
|
8
|
-
def repetition_hash(array)
|
9
|
-
|
10
|
-
|
11
|
-
result = array.inject({}) { |key, value| key[value] = array.count(value.to_f); key }
|
12
|
-
{ hash_result: result, max_repetition: result.values.max }
|
13
|
-
end
|
15
|
+
def repetition_hash(array)
|
16
|
+
{ hash_result: build_repetition_result(array), max_repetition: build_repetition_result(array).values.max }
|
17
|
+
end
|
14
18
|
|
15
|
-
def
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
19
|
+
def build_hash_result(result)
|
20
|
+
result[:hash_result].select { |key, value| value == result[:max_repetition] }
|
21
|
+
end
|
22
|
+
|
23
|
+
def build_repetition_result(array)
|
24
|
+
array.inject({}) { |key, value| key[value] = array.count(value.to_f); key }
|
25
|
+
end
|
26
|
+
|
27
|
+
def get_unique_mode(array)
|
28
|
+
# only for Ruby versions bigger than 1.8.7 -> http://apidock.com/ruby/v1_8_7_72/Enumerable/max_by
|
29
|
+
if valid_array?(array)
|
30
|
+
clean_array(array).max_by { |x| clean_array(array).count(x) }
|
31
|
+
end
|
32
|
+
end
|
20
33
|
end
|
data/lib/average/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
|
2
|
-
VERSION = "3.
|
1
|
+
class Average
|
2
|
+
VERSION = "3.1"
|
3
3
|
end
|
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Average do
|
4
4
|
|
5
|
-
let(:int_array) { [3,4,5]
|
5
|
+
let(:int_array) { [3,4,5] }
|
6
6
|
|
7
7
|
describe '.mean' do
|
8
8
|
context 'should give back the same result as' do
|
@@ -28,4 +28,12 @@ describe Average do
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
+
describe '.unique_mode' do
|
32
|
+
context 'should give back the same result as ' do
|
33
|
+
it 'get_unique_mode([X,X,X,X])' do
|
34
|
+
expect(int_array.unique_mode).to eq(get_unique_mode(int_array))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
31
39
|
end
|
data/spec/average_helper_spec.rb
CHANGED
@@ -97,11 +97,11 @@ describe Average do
|
|
97
97
|
end
|
98
98
|
|
99
99
|
describe '#clean_array' do
|
100
|
-
context 'with an array that
|
100
|
+
context 'with an array that has a valid mixed-array structure' do
|
101
101
|
it 'should return an array without string and with the correct numeric format' do
|
102
102
|
expect(clean_array(valid_array)).to eq([3, 4.0, 5, 2, 0.3])
|
103
103
|
end
|
104
104
|
end
|
105
105
|
end
|
106
106
|
|
107
|
-
end
|
107
|
+
end
|
data/spec/mode_spec.rb
CHANGED
@@ -7,6 +7,8 @@ describe Average do
|
|
7
7
|
let(:mode_array) { [1,1,2,2,3,4] }
|
8
8
|
|
9
9
|
let(:mixed_array) { [3, 4.0, 5, 2.0, 3, 1.0] }
|
10
|
+
let(:array_with_two_modes) { [1, 2, 2, 2, 3, 3, 7, 7, 7, 9] }
|
11
|
+
let(:array_with_one_mode) { [2, 4, 6, 14, 21, 24, 229, 24, 24, 39] }
|
10
12
|
|
11
13
|
describe '#get_mode' do
|
12
14
|
|
@@ -17,36 +19,36 @@ describe Average do
|
|
17
19
|
end
|
18
20
|
|
19
21
|
context 'with a empty array' do
|
20
|
-
it 'should return
|
22
|
+
it 'should return nil' do
|
21
23
|
expect(get_mode([])).to eq(nil)
|
22
24
|
end
|
23
25
|
end
|
24
26
|
|
25
27
|
context 'with a nil object' do
|
26
|
-
it 'should return a
|
28
|
+
it 'should return a nil' do
|
27
29
|
expect(get_mode([])).to eq(nil)
|
28
30
|
end
|
29
31
|
end
|
30
32
|
|
31
33
|
end
|
32
34
|
|
33
|
-
describe '#
|
35
|
+
describe '#get_unique_mode' do
|
34
36
|
|
35
37
|
context 'with a array of integers' do
|
36
38
|
it 'should calculate the correct mode returning only one mode' do
|
37
|
-
expect(
|
39
|
+
expect(get_unique_mode(mode_array)).to eq(1)
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
41
43
|
context 'with a empty array' do
|
42
44
|
it 'should return nil' do
|
43
|
-
expect(
|
45
|
+
expect(get_unique_mode([])).to eq(nil)
|
44
46
|
end
|
45
47
|
end
|
46
48
|
|
47
49
|
context 'with a nil object' do
|
48
50
|
it 'should return nil' do
|
49
|
-
expect(
|
51
|
+
expect(get_unique_mode(nil)).to eq(nil)
|
50
52
|
end
|
51
53
|
end
|
52
54
|
|
@@ -71,17 +73,26 @@ describe Average do
|
|
71
73
|
end
|
72
74
|
|
73
75
|
context 'with a empty array' do
|
74
|
-
it 'should return
|
75
|
-
expect(repetition_hash([])).to eql(nil)
|
76
|
+
it 'should return a hash with empty values' do
|
77
|
+
expect(repetition_hash([])).to eql({:hash_result=>{}, :max_repetition=>nil})
|
76
78
|
end
|
77
79
|
end
|
78
80
|
|
79
|
-
|
80
|
-
|
81
|
-
|
81
|
+
end
|
82
|
+
|
83
|
+
describe 'testing returned values' do
|
84
|
+
|
85
|
+
context 'with an array that has two modes' do
|
86
|
+
it 'should return an array with two values' do
|
87
|
+
expect(get_mode(array_with_two_modes)).to eq([2, 7])
|
82
88
|
end
|
83
89
|
end
|
84
90
|
|
91
|
+
context 'with an array that has one modes' do
|
92
|
+
it 'should return an array with two values' do
|
93
|
+
expect(get_mode(array_with_one_mode)).to eq(24)
|
94
|
+
end
|
95
|
+
end
|
85
96
|
end
|
86
97
|
|
87
|
-
end
|
98
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: average
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '3.
|
4
|
+
version: '3.1'
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-03
|
12
|
+
date: 2015-11-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|