active_object 3.1.0 → 4.0.0
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.
- checksums.yaml +4 -4
- data/.DS_Store +0 -0
- data/.fasterer.yml +19 -0
- data/.reek +39 -0
- data/.rubocop.yml +38 -0
- data/Gemfile +1 -1
- data/README.md +224 -239
- data/Rakefile +1 -1
- data/active_object.gemspec +19 -16
- data/bin/console +4 -4
- data/bin/rake +6 -7
- data/lib/.DS_Store +0 -0
- data/lib/active_object.rb +4 -33
- data/lib/active_object/.DS_Store +0 -0
- data/lib/active_object/array.rb +55 -41
- data/lib/active_object/date.rb +17 -22
- data/lib/active_object/enumerable.rb +73 -56
- data/lib/active_object/hash.rb +47 -37
- data/lib/active_object/integer.rb +8 -9
- data/lib/active_object/numeric.rb +132 -122
- data/lib/active_object/object.rb +10 -10
- data/lib/active_object/range.rb +1 -1
- data/lib/active_object/settings.rb +17 -0
- data/lib/active_object/string.rb +93 -90
- data/lib/active_object/time.rb +37 -48
- data/lib/active_object/version.rb +1 -1
- data/lib/generators/active_object/install_generator.rb +6 -8
- data/lib/generators/active_object/templates/install.rb +1 -1
- metadata +51 -3
- data/lib/active_object/configuration.rb +0 -21
data/Rakefile
CHANGED
data/active_object.gemspec
CHANGED
@@ -1,27 +1,30 @@
|
|
1
1
|
# coding: utf-8
|
2
|
-
lib = File.expand_path(
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require
|
4
|
+
require 'active_object/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
7
|
+
spec.name = 'active_object'
|
8
8
|
spec.version = ActiveObject::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
9
|
+
spec.authors = ['Juan Gomez']
|
10
|
+
spec.email = ['j.gomez@drexed.com']
|
11
11
|
|
12
|
-
spec.summary =
|
13
|
-
spec.description =
|
14
|
-
spec.homepage =
|
15
|
-
spec.license =
|
12
|
+
spec.summary = 'Gem for commonly used ruby object helpers.'
|
13
|
+
spec.description = 'Class extensions of commonly used ruby object helpers.'
|
14
|
+
spec.homepage = 'http://drexed.github.io/active_object'
|
15
|
+
spec.license = 'MIT'
|
16
16
|
|
17
17
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
-
spec.bindir =
|
18
|
+
spec.bindir = 'exe'
|
19
19
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
-
spec.require_paths = [
|
20
|
+
spec.require_paths = ['lib']
|
21
21
|
|
22
|
-
spec.add_development_dependency
|
23
|
-
spec.add_development_dependency
|
24
|
-
spec.add_development_dependency
|
25
|
-
spec.add_development_dependency
|
26
|
-
spec.add_development_dependency
|
22
|
+
spec.add_development_dependency 'bundler'
|
23
|
+
spec.add_development_dependency 'coveralls'
|
24
|
+
spec.add_development_dependency 'rake'
|
25
|
+
spec.add_development_dependency 'rspec'
|
26
|
+
spec.add_development_dependency 'generator_spec'
|
27
|
+
spec.add_development_dependency 'fasterer'
|
28
|
+
spec.add_development_dependency 'reek'
|
29
|
+
spec.add_development_dependency 'rubocop'
|
27
30
|
end
|
data/bin/console
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'active_object'
|
5
5
|
|
6
6
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
7
|
# with your gem easier. You can also use a different console, if you like.
|
8
8
|
|
9
9
|
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
-
# require
|
10
|
+
# require 'pry'
|
11
11
|
# Pry.start
|
12
12
|
|
13
|
-
require
|
13
|
+
require 'irb'
|
14
14
|
IRB.start
|
data/bin/rake
CHANGED
@@ -2,15 +2,14 @@
|
|
2
2
|
#
|
3
3
|
# This file was generated by Bundler.
|
4
4
|
#
|
5
|
-
# The application
|
5
|
+
# The application 'rake' is installed as part of a gem, and
|
6
6
|
# this file is here to facilitate running it.
|
7
7
|
#
|
8
8
|
|
9
|
-
require
|
10
|
-
ENV[
|
11
|
-
Pathname.new(__FILE__).realpath)
|
9
|
+
require 'pathname'
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', Pathname.new(__FILE__).realpath)
|
12
11
|
|
13
|
-
require
|
14
|
-
require
|
12
|
+
require 'rubygems'
|
13
|
+
require 'bundler/setup'
|
15
14
|
|
16
|
-
load Gem.bin_path(
|
15
|
+
load Gem.bin_path('rake', 'rake')
|
data/lib/.DS_Store
ADDED
Binary file
|
data/lib/active_object.rb
CHANGED
@@ -1,35 +1,6 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
module ActiveObject
|
5
|
-
|
6
|
-
class << self
|
7
|
-
attr_accessor :configuration
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.configuration
|
11
|
-
@configuration ||= Configuration.new
|
12
|
-
end
|
13
|
-
|
14
|
-
def self.configuration=(config)
|
15
|
-
@configuration = config
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.configure
|
19
|
-
yield(configuration)
|
1
|
+
%w(version settings array date enumerable hash integer numeric object range string time)
|
2
|
+
.each do |file_name|
|
3
|
+
require "active_object/#{file_name}"
|
20
4
|
end
|
21
5
|
|
22
|
-
|
23
|
-
|
24
|
-
require "active_object/array"
|
25
|
-
require "active_object/date"
|
26
|
-
require "active_object/enumerable"
|
27
|
-
require "active_object/hash"
|
28
|
-
require "active_object/integer"
|
29
|
-
require "active_object/numeric"
|
30
|
-
require "active_object/object"
|
31
|
-
require "active_object/range"
|
32
|
-
require "active_object/string"
|
33
|
-
require "active_object/time"
|
34
|
-
|
35
|
-
require "generators/active_object/install_generator"
|
6
|
+
require 'generators/active_object/install_generator'
|
Binary file
|
data/lib/active_object/array.rb
CHANGED
@@ -30,25 +30,26 @@ module ActiveObject::Array
|
|
30
30
|
|
31
31
|
def delete_values(*args)
|
32
32
|
result = []
|
33
|
-
args.each { |
|
33
|
+
args.each { |val| result << delete(val) }
|
34
34
|
result
|
35
35
|
end
|
36
36
|
|
37
37
|
def dig(key, *rest)
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
38
|
+
value = (self[key] rescue nil)
|
39
|
+
return if value.nil?
|
40
|
+
|
41
|
+
if rest.empty?
|
42
|
+
value
|
43
|
+
elsif value.respond_to?(:dig)
|
44
|
+
value.dig(*rest)
|
44
45
|
end
|
45
46
|
end
|
46
47
|
|
47
|
-
def duplicates(minimum=2)
|
48
|
+
def duplicates(minimum = 2)
|
48
49
|
hash = Hash.new(0)
|
49
50
|
|
50
|
-
each { |
|
51
|
-
hash.delete_if { |
|
51
|
+
each { |val| hash[val] += 1 }
|
52
|
+
hash.delete_if { |_, val| val < minimum }.keys
|
52
53
|
end
|
53
54
|
|
54
55
|
def from(position)
|
@@ -58,32 +59,36 @@ module ActiveObject::Array
|
|
58
59
|
def groups(number)
|
59
60
|
return([]) if number <= 0
|
60
61
|
|
61
|
-
|
62
|
-
collection = (0..(
|
63
|
-
|
62
|
+
num, rem = length.divmod(number)
|
63
|
+
collection = (0..(num - 1)).collect { |val| self[(val * number), number] }
|
64
|
+
rem.positive? ? collection << self[-rem, rem] : collection
|
64
65
|
end
|
65
66
|
|
66
|
-
|
67
|
+
# rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/AbcSize
|
68
|
+
def in_groups(number, fill_with = nil)
|
67
69
|
collection_length = length
|
68
70
|
division = collection_length.div(number)
|
69
71
|
modulo = collection_length % number
|
70
72
|
|
71
73
|
collection = []
|
72
74
|
start = 0
|
73
|
-
number.times do |
|
74
|
-
|
75
|
+
number.times do |int|
|
76
|
+
mod_gt_zero = modulo.positive?
|
77
|
+
grouping = division + (mod_gt_zero && modulo > int ? 1 : 0)
|
75
78
|
collection << last_group = slice(start, grouping)
|
76
|
-
last_group << fill_with if fill_with != false &&
|
79
|
+
last_group << fill_with if fill_with != false && mod_gt_zero && grouping == division
|
77
80
|
start += grouping
|
78
81
|
end
|
79
82
|
|
80
|
-
block_given? ? collection.each { |
|
83
|
+
block_given? ? collection.each { |val| yield(val) } : collection
|
81
84
|
end
|
85
|
+
# rubocop:enable Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/AbcSize
|
82
86
|
|
83
|
-
|
87
|
+
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
88
|
+
def in_groups_of(number, fill_with = nil)
|
84
89
|
if number.to_i <= 0
|
85
90
|
raise ArgumentError,
|
86
|
-
|
91
|
+
"Group length must be a positive integer, was #{number.inspect}"
|
87
92
|
end
|
88
93
|
|
89
94
|
if fill_with == false
|
@@ -93,17 +98,20 @@ module ActiveObject::Array
|
|
93
98
|
collection = dup.concat(Array.new(padding, fill_with))
|
94
99
|
end
|
95
100
|
|
96
|
-
|
101
|
+
sliced_collection = collection.each_slice(number)
|
102
|
+
|
103
|
+
block_given? ? sliced_collection { |val| yield(val) } : sliced_collection.to_a
|
97
104
|
end
|
105
|
+
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
|
98
106
|
|
99
107
|
def percentile(percentage)
|
100
|
-
|
108
|
+
total_size = size
|
101
109
|
|
102
|
-
if
|
103
|
-
index = (
|
104
|
-
|
110
|
+
if total_size > 1
|
111
|
+
index = (total_size * percentage) / 100.0
|
112
|
+
sort[index]
|
105
113
|
else
|
106
|
-
|
114
|
+
first
|
107
115
|
end
|
108
116
|
end
|
109
117
|
|
@@ -111,31 +119,33 @@ module ActiveObject::Array
|
|
111
119
|
hash = Hash.new(0.0)
|
112
120
|
differ = 0.0
|
113
121
|
|
114
|
-
each do |
|
115
|
-
hash[
|
122
|
+
each do |val|
|
123
|
+
hash[val] += 1.0
|
116
124
|
differ += 1.0
|
117
125
|
end
|
118
126
|
|
119
|
-
hash.
|
127
|
+
hash.each_key { |val| hash[val] /= differ }
|
120
128
|
hash
|
121
129
|
end
|
122
130
|
|
123
131
|
def reject_values(*args)
|
124
|
-
reject { |
|
132
|
+
reject { |val| args.include?(val) }
|
125
133
|
end
|
126
134
|
|
127
135
|
def sample!
|
128
136
|
delete_at(Random.rand(length - 1))
|
129
137
|
end
|
130
138
|
|
131
|
-
|
139
|
+
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
140
|
+
def split(number = nil)
|
132
141
|
if block_given?
|
133
|
-
|
142
|
+
each_with_object([[]]) do |element, results|
|
134
143
|
yield(element) ? (results << []) : (results.last << element)
|
135
|
-
results
|
136
144
|
end
|
137
145
|
else
|
138
|
-
results
|
146
|
+
results = [[]]
|
147
|
+
arr = dup
|
148
|
+
|
139
149
|
until arr.empty?
|
140
150
|
if (idx = arr.index(number))
|
141
151
|
results.last.concat(arr.shift(idx))
|
@@ -145,12 +155,14 @@ module ActiveObject::Array
|
|
145
155
|
results.last.concat(arr.shift(arr.length))
|
146
156
|
end
|
147
157
|
end
|
158
|
+
|
148
159
|
results
|
149
160
|
end
|
150
161
|
end
|
162
|
+
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
|
151
163
|
|
152
164
|
def strip
|
153
|
-
reject
|
165
|
+
reject(&:blank?)
|
154
166
|
end
|
155
167
|
|
156
168
|
def strip!
|
@@ -161,17 +173,18 @@ module ActiveObject::Array
|
|
161
173
|
position >= 0 ? first(position + 1) : self[0..position]
|
162
174
|
end
|
163
175
|
|
164
|
-
|
176
|
+
# rubocop:disable Metrics/MethodLength
|
177
|
+
def to_sentence(options = {})
|
165
178
|
default_connectors = {
|
166
|
-
words_connector:
|
167
|
-
two_words_connector:
|
168
|
-
last_word_connector:
|
179
|
+
words_connector: ', ',
|
180
|
+
two_words_connector: ' and ',
|
181
|
+
last_word_connector: ', and '
|
169
182
|
}
|
170
183
|
options = default_connectors.merge!(options)
|
171
184
|
|
172
185
|
case length
|
173
186
|
when 0
|
174
|
-
|
187
|
+
''
|
175
188
|
when 1
|
176
189
|
self[0].to_s.dup
|
177
190
|
when 2
|
@@ -180,7 +193,8 @@ module ActiveObject::Array
|
|
180
193
|
"#{self[0...-1].join(options[:words_connector])}#{options[:last_word_connector]}#{self[-1]}"
|
181
194
|
end
|
182
195
|
end
|
196
|
+
# rubocop:enable Metrics/MethodLength
|
183
197
|
|
184
198
|
end
|
185
199
|
|
186
|
-
Array.send(:include, ActiveObject::Array) if ActiveObject.
|
200
|
+
Array.send(:include, ActiveObject::Array) if ActiveObject::Settings.config.autoload_array
|
data/lib/active_object/date.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
module ActiveObject::Date
|
2
|
-
|
3
2
|
MINUTE = 60.0
|
4
3
|
HOUR = MINUTE * 60.0
|
5
4
|
DAY = HOUR * 24.0
|
@@ -10,26 +9,22 @@ module ActiveObject::Date
|
|
10
9
|
MILLENNIUM = CENTURY * 10.0
|
11
10
|
|
12
11
|
STRING_UNITS = {
|
13
|
-
d:
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
yy: "y", yr: "y", yyyy: "Y", year: "Y"
|
21
|
-
}
|
12
|
+
d: 'd', day: 'd', day_padded: 'd', dd: '-d', Day: '-d', day_unpadded: '-d', ddd: '_d',
|
13
|
+
DAY: '_d', day_blank: '_d', dddd: 'j', day_of_the_year: 'j', m: 'm', month: 'm', yyyy: 'Y',
|
14
|
+
month_padded: 'm', mm: '-m', Month: '-m', month_unpadded: '-m', mmm: '_m', MONTH: '_m',
|
15
|
+
month_blank: '_m', mmmm: 'B', month_name: 'B', mmmmm: 'b', month_name_abbr: 'b', w: 'u',
|
16
|
+
weekday: 'u', ww: 'w', weekday_offset: 'w', www: 'A', weekday_name: 'A', wwww: 'a', year: 'Y',
|
17
|
+
weekday_name_abbr: 'a', wwwww: 'W', week: 'W', wwwwww: 'U', week_offset: 'U', yy: 'y', yr: 'y'
|
18
|
+
}.freeze
|
22
19
|
KEY_UNITS = {
|
23
|
-
month:
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
day: "%B %-d", day_abbr: "%b %-d", day_iso: "%m-%d"
|
32
|
-
}
|
20
|
+
month: '%m', month_padded: '%m', month_unpadded: '%-m', month_blank: '%_m', month_name: '%B',
|
21
|
+
month_name_abbr: '%b', month_year: '%m %Y', month_padded_year: '%m %Y', day_iso: '%m-%d',
|
22
|
+
month_unpadded_year: '%-m %Y', month_blank_year: '%_m %Y', month_name_year: '%B %Y',
|
23
|
+
month_name_abbr_year: '%b %Y', weekday: '%d', weekday_padded: '%d', weekday_unpadded: '%-d',
|
24
|
+
weekday_blank: '%_d', weekday_name: '%A', weekday_name_abbr: '%a', yr: '%y', year_abbr: '%y',
|
25
|
+
year: '%Y', date: '%B %-d, %Y', date_abbr: '%b %-d, %Y', date_iso: '%Y-%m-%d', day: '%B %-d',
|
26
|
+
day_abbr: '%b %-d'
|
27
|
+
}.freeze
|
33
28
|
|
34
29
|
def count_centuries_since(time)
|
35
30
|
count_seconds_since(time) / CENTURY
|
@@ -96,7 +91,7 @@ module ActiveObject::Date
|
|
96
91
|
strftime(string.join)
|
97
92
|
end
|
98
93
|
|
99
|
-
def to_format(key
|
94
|
+
def to_format(key = :datetime_iso)
|
100
95
|
strftime(KEY_UNITS.fetch(key.to_sym))
|
101
96
|
end
|
102
97
|
|
@@ -104,4 +99,4 @@ module ActiveObject::Date
|
|
104
99
|
|
105
100
|
end
|
106
101
|
|
107
|
-
Date.send(:include, ActiveObject::Date) if ActiveObject.
|
102
|
+
Date.send(:include, ActiveObject::Date) if ActiveObject::Settings.config.autoload_date
|
@@ -1,39 +1,43 @@
|
|
1
1
|
module Enumerable
|
2
2
|
|
3
|
+
# rubocop:disable Lint/UnusedMethodArgument
|
3
4
|
def cluster(&block)
|
4
5
|
result = []
|
5
|
-
each do |
|
6
|
-
|
7
|
-
|
6
|
+
each do |ele|
|
7
|
+
last_res = result.last
|
8
|
+
|
9
|
+
if last_res && (yield(last_res.last) == yield(ele))
|
10
|
+
last_res << ele
|
8
11
|
else
|
9
|
-
result << [
|
12
|
+
result << [ele]
|
10
13
|
end
|
11
14
|
end
|
12
15
|
result
|
13
16
|
end
|
17
|
+
# rubocop:enable Lint/UnusedMethodArgument
|
14
18
|
|
15
|
-
def difference(identity=0, &block)
|
19
|
+
def difference(identity = 0, &block)
|
16
20
|
if block_given?
|
17
21
|
map(&block).difference(identity)
|
18
22
|
else
|
19
|
-
inject { |
|
23
|
+
inject { |key, val| key - val } || identity
|
20
24
|
end
|
21
25
|
end
|
22
26
|
|
23
|
-
def divisible(identity=0, &block)
|
27
|
+
def divisible(identity = 0, &block)
|
24
28
|
if block_given?
|
25
29
|
map(&block).divisible(identity)
|
26
30
|
else
|
27
|
-
inject { |
|
31
|
+
inject { |key, val| key / val } || identity
|
28
32
|
end
|
29
33
|
end
|
30
34
|
|
31
|
-
def drop_last(
|
35
|
+
def drop_last(num)
|
32
36
|
collection_length = to_a.length
|
33
37
|
|
34
|
-
return(self) if
|
38
|
+
return(self) if num > collection_length
|
35
39
|
|
36
|
-
self[0...(collection_length -
|
40
|
+
self[0...(collection_length - num)]
|
37
41
|
end
|
38
42
|
|
39
43
|
def drop_last_if
|
@@ -41,16 +45,20 @@ module Enumerable
|
|
41
45
|
|
42
46
|
result = []
|
43
47
|
dropping = true
|
44
|
-
reverse_each do |
|
45
|
-
result.unshift(
|
48
|
+
reverse_each do |val|
|
49
|
+
result.unshift(val) unless dropping &&= yield(val)
|
46
50
|
end
|
47
51
|
result
|
48
52
|
end
|
49
53
|
|
50
|
-
def exactly?(
|
54
|
+
def exactly?(num)
|
51
55
|
found_count = 0
|
52
|
-
block_given?
|
53
|
-
|
56
|
+
if block_given?
|
57
|
+
each { |*opt| found_count += 1 if yield(*opt) }
|
58
|
+
else
|
59
|
+
each { |opt| found_count += 1 if opt }
|
60
|
+
end
|
61
|
+
found_count > num ? false : num == found_count
|
54
62
|
end
|
55
63
|
|
56
64
|
def exclude?(object)
|
@@ -58,30 +66,32 @@ module Enumerable
|
|
58
66
|
end
|
59
67
|
|
60
68
|
def expand
|
61
|
-
map { |
|
69
|
+
map { |val| val.is_a?(Enumerable) ? val.expand : val }
|
62
70
|
end
|
63
71
|
|
64
|
-
def exponential(identity=0, &block)
|
72
|
+
def exponential(identity = 0, &block)
|
65
73
|
if block_given?
|
66
74
|
map(&block).exponential(identity)
|
67
75
|
else
|
68
|
-
inject { |
|
76
|
+
inject { |key, val| key**val } || identity
|
69
77
|
end
|
70
78
|
end
|
71
79
|
|
72
80
|
def frequencies
|
73
|
-
each_with_object(Hash.new(0)) { |
|
81
|
+
each_with_object(Hash.new(0)) { |key, hsh| hsh[key] += 1 }
|
74
82
|
end
|
75
83
|
|
84
|
+
# rubocop:disable Style/CaseEquality
|
76
85
|
def incase?(object)
|
77
|
-
any? { |
|
86
|
+
any? { |val| object === val }
|
78
87
|
end
|
88
|
+
# rubocop:enable Style/CaseEquality
|
79
89
|
|
80
90
|
def many?
|
81
91
|
found_count = 0
|
82
92
|
if block_given?
|
83
|
-
any? do |
|
84
|
-
found_count += 1 if yield
|
93
|
+
any? do |val|
|
94
|
+
found_count += 1 if yield val
|
85
95
|
found_count > 1
|
86
96
|
end
|
87
97
|
else
|
@@ -89,16 +99,16 @@ module Enumerable
|
|
89
99
|
end
|
90
100
|
end
|
91
101
|
|
92
|
-
def max(identity=0)
|
93
|
-
(length rescue count)
|
102
|
+
def max(identity = 0)
|
103
|
+
(length rescue count).positive? ? sort.last : identity
|
94
104
|
end
|
95
105
|
|
96
|
-
def min(identity=0)
|
97
|
-
(length rescue count)
|
106
|
+
def min(identity = 0)
|
107
|
+
(length rescue count).positive? ? sort.first : identity
|
98
108
|
end
|
99
109
|
|
100
|
-
def mean(identity=0)
|
101
|
-
return(identity) unless length
|
110
|
+
def mean(identity = 0)
|
111
|
+
return(identity) unless length.positive?
|
102
112
|
|
103
113
|
collection_length = length
|
104
114
|
sum.to_f / collection_length.to_f
|
@@ -106,44 +116,47 @@ module Enumerable
|
|
106
116
|
|
107
117
|
alias_method :average, :mean
|
108
118
|
|
109
|
-
def median(identity=0)
|
119
|
+
def median(identity = 0)
|
110
120
|
collection_length = length.to_f
|
111
121
|
collection_sorted = sort
|
112
122
|
|
113
123
|
return(identity) unless collection_length > 0.0
|
124
|
+
half_collection = collection_length / 2.0
|
125
|
+
sorted_collection = collection_sorted[half_collection]
|
114
126
|
|
115
127
|
if (collection_length % 2).zero?
|
116
|
-
(collection_sorted[
|
128
|
+
(collection_sorted[half_collection - 1.0] + sorted_collection) / 2.0
|
117
129
|
else
|
118
|
-
|
130
|
+
sorted_collection
|
119
131
|
end
|
120
132
|
end
|
121
133
|
|
122
|
-
|
123
|
-
|
134
|
+
# rubocop:disable Metrics/AbcSize
|
135
|
+
def mode(identity = 0)
|
136
|
+
return(identity) unless length.positive?
|
124
137
|
|
125
|
-
frequency_distribution =
|
126
|
-
frequency_top_two = frequency_distribution.
|
138
|
+
frequency_distribution = each_with_object(Hash.new(0)) { |val, hsh| hsh[val] += 1 }
|
139
|
+
frequency_top_two = frequency_distribution.sort_by { |_, val| -val }.take(2)
|
140
|
+
top_two_first = frequency_top_two.first
|
127
141
|
|
128
|
-
if frequency_top_two.length ==
|
129
|
-
frequency_top_two.first.first
|
130
|
-
elsif frequency_top_two.first.last == frequency_top_two.last.last
|
142
|
+
if frequency_top_two.length != 1 && top_two_first.last == frequency_top_two.last.last
|
131
143
|
nil
|
132
144
|
else
|
133
|
-
|
145
|
+
top_two_first.first
|
134
146
|
end
|
135
147
|
end
|
148
|
+
# rubocop:ensable Metrics/AbcSize
|
136
149
|
|
137
|
-
def multiple(identity=0, &block)
|
150
|
+
def multiple(identity = 0, &block)
|
138
151
|
if block_given?
|
139
152
|
map(&block).multiple(identity)
|
140
153
|
else
|
141
|
-
inject { |
|
154
|
+
inject { |key, val| key * val } || identity
|
142
155
|
end
|
143
156
|
end
|
144
157
|
|
145
|
-
def range(identity=0)
|
146
|
-
return(identity) unless length
|
158
|
+
def range(identity = 0)
|
159
|
+
return(identity) unless length.positive?
|
147
160
|
|
148
161
|
collection_sorted = sort
|
149
162
|
collection_sorted.last - collection_sorted.first
|
@@ -151,47 +164,51 @@ module Enumerable
|
|
151
164
|
|
152
165
|
def several?
|
153
166
|
found_count = 0
|
154
|
-
block_given?
|
155
|
-
|
167
|
+
if block_given?
|
168
|
+
each { |*opt| found_count += 1 if yield(*opt) }
|
169
|
+
else
|
170
|
+
each { |opt| found_count += 1 if opt }
|
171
|
+
end
|
172
|
+
found_count > 1 ? true : false
|
156
173
|
end
|
157
174
|
|
158
|
-
def standard_deviation(identity=0)
|
175
|
+
def standard_deviation(identity = 0)
|
159
176
|
return(identity) if length < 2
|
160
177
|
|
161
178
|
Math.sqrt(variance)
|
162
179
|
end
|
163
180
|
|
164
|
-
def sum(identity=0, &block)
|
181
|
+
def sum(identity = 0, &block)
|
165
182
|
if block_given?
|
166
183
|
map(&block).sum(identity)
|
167
184
|
else
|
168
|
-
inject { |
|
185
|
+
inject { |sum, val| sum + val } || identity
|
169
186
|
end
|
170
187
|
end
|
171
188
|
|
172
|
-
def take_last(
|
189
|
+
def take_last(num)
|
173
190
|
collection_length = to_a.length
|
174
191
|
|
175
|
-
return(self) if
|
192
|
+
return(self) if num > collection_length
|
176
193
|
|
177
|
-
self[(collection_length -
|
194
|
+
self[(collection_length - num)..-1]
|
178
195
|
end
|
179
196
|
|
180
197
|
def take_last_if
|
181
198
|
return(to_enum(:take_last_if)) unless block_given?
|
182
199
|
|
183
200
|
result = []
|
184
|
-
reverse_each { |
|
201
|
+
reverse_each { |val| yield(val) ? result.unshift(val) : break }
|
185
202
|
result
|
186
203
|
end
|
187
204
|
|
188
|
-
def variance(identity=0)
|
205
|
+
def variance(identity = 0)
|
189
206
|
collection_length = length
|
190
207
|
|
191
208
|
return(identity) if collection_length <= 1
|
192
209
|
|
193
|
-
|
194
|
-
|
210
|
+
total = inject(0.0) { |sum, val| sum + (val - mean)**2.0 }
|
211
|
+
total.to_f / (collection_length.to_f - 1.0)
|
195
212
|
end
|
196
213
|
|
197
214
|
end
|