ruby_extended 1.1.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 +7 -0
- data/.gitignore +10 -0
- data/.rspec +3 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +45 -0
- data/badges/coverage.svg +1 -0
- data/badges/license.svg +1 -0
- data/badges/ruby.svg +1 -0
- data/documentation/array.md +226 -0
- data/documentation/hash.md +22 -0
- data/documentation/number.md +39 -0
- data/documentation/object.md +17 -0
- data/documentation/readme.md +7 -0
- data/documentation/string.md +156 -0
- data/lib/ruby_extended.rb +5 -0
- data/lib/ruby_extended/array.rb +197 -0
- data/lib/ruby_extended/hash.rb +30 -0
- data/lib/ruby_extended/number.rb +54 -0
- data/lib/ruby_extended/object.rb +32 -0
- data/lib/ruby_extended/string.rb +59 -0
- data/lib/ruby_extended/version.rb +3 -0
- data/readme.md +24 -0
- data/ruby_extended.gemspec +24 -0
- data/spec/ruby_extend_array_spec.rb +412 -0
- data/spec/ruby_extend_hash_spec.rb +37 -0
- data/spec/ruby_extend_number_spec.rb +114 -0
- data/spec/ruby_extend_object_spec.rb +49 -0
- data/spec/ruby_extend_string_spec.rb +147 -0
- data/spec/spec_helper.rb +8 -0
- metadata +88 -0
@@ -0,0 +1,197 @@
|
|
1
|
+
class Array
|
2
|
+
require 'unicode_utils'
|
3
|
+
|
4
|
+
|
5
|
+
def sort_lv(&block)
|
6
|
+
lang = [
|
7
|
+
%w[e ē], %w[u ū], %w[i ī], %w[a ā], %w[s š], %w[g ģ], %w[k ķ], %w[l ļ],
|
8
|
+
%w[z ž], %w[c č], %w[n ņ], %w[E Ē], %w[U Ū], %w[I I], %w[A Ā], %w[S Š],
|
9
|
+
%w[G Ģ], %w[K Ķ], %w[L Ļ], %w[Z Ž], %w[C Č], %w[N Ņ]
|
10
|
+
]
|
11
|
+
|
12
|
+
self.sort_by do |item|
|
13
|
+
value = (block_given? ? yield(item) : item)
|
14
|
+
lang.each do |en, lv|
|
15
|
+
value = UnicodeUtils.downcase(value).gsub(lv, en)
|
16
|
+
end
|
17
|
+
value
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
def tabulate(num, o = {})
|
23
|
+
return nil if num < 1
|
24
|
+
return self if num == 1
|
25
|
+
|
26
|
+
split_by = o.has_key?(:split_by) ? o[:split_by] : :columns
|
27
|
+
direction = o.has_key?(:direction) ? o[:direction] : :horizontal
|
28
|
+
arr, res = self, []
|
29
|
+
i = (arr.length / num.to_f).round
|
30
|
+
|
31
|
+
if direction == :horizontal
|
32
|
+
ii = 0
|
33
|
+
|
34
|
+
if split_by == :columns
|
35
|
+
rows = ( (i == 1) ? [0] : (0..i - 1).to_a )
|
36
|
+
cells = ( (num == 1) ? [0] : (0..num - 1).to_a )
|
37
|
+
end
|
38
|
+
|
39
|
+
if split_by == :rows
|
40
|
+
rows = ( (num == 1) ? [0] : (0..num - 1).to_a )
|
41
|
+
cells = ( (i == 1) ? [0] : (0..i - 1).to_a )
|
42
|
+
end
|
43
|
+
|
44
|
+
rows.each do |row_i|
|
45
|
+
cells.each do |cell_i|
|
46
|
+
res[row_i] = [] if res[row_i].nil?
|
47
|
+
res[row_i][cell_i] = arr[ii]
|
48
|
+
ii = ii + 1
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
res
|
53
|
+
end
|
54
|
+
|
55
|
+
if direction == :vertical
|
56
|
+
|
57
|
+
if split_by == :columns
|
58
|
+
(0..(i - 1)).to_a.each do |r_i|
|
59
|
+
res[r_i] = (r_i).step(arr.size * 5, i).to_a.slice(0, num).map {|ii| arr[ii]}
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
if split_by == :rows
|
64
|
+
(0..(num - 1)).to_a.each do |r_i|
|
65
|
+
res[r_i] = (r_i).step(arr.length * 5, num).to_a.slice(0, i).map {|ii| arr[ii]}
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
res
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
def sample_index(count=1, offset: nil)
|
75
|
+
indexes = (0..(self.length - 1)).to_a
|
76
|
+
indexes = indexes.slice(offset + 1, indexes.length) if offset
|
77
|
+
return nil if indexes.nil?
|
78
|
+
result = indexes.sample(count)
|
79
|
+
result = result.first if count == 1
|
80
|
+
result
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
def uniq_by_key(key)
|
85
|
+
keys, res, found = [], [], false
|
86
|
+
self.each do |item|
|
87
|
+
found = true if item.has_key?(key)
|
88
|
+
next if keys.include?(item[key])
|
89
|
+
res << item
|
90
|
+
keys << item[key]
|
91
|
+
end
|
92
|
+
found ? res : self
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
def duplicates(options={})
|
97
|
+
self.select {|e| self.count(e) > 1}.uniq.map do |v|
|
98
|
+
options[:full] ? { item: v, count: self.count(v) } : v
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
def sum(o={})
|
104
|
+
res, str = [], false
|
105
|
+
|
106
|
+
self.map do |e|
|
107
|
+
ce = o[:key] ? e[o[:key]] : e
|
108
|
+
if o[:only_numbers]
|
109
|
+
res << ce if ce.is_a?(Numeric)
|
110
|
+
else
|
111
|
+
str = true if ce.kind_of?(String)
|
112
|
+
res << ce unless ce.nil?
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
str ? res.join('') : res.reduce(:+)
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
def to_tree(o = {})
|
121
|
+
o[:id_key] = :id unless o.has_key?(:id_key)
|
122
|
+
o[:parent_id_key] = :parent_id unless o.has_key?(:parent_id_key)
|
123
|
+
o[:children_key] = :children unless o.has_key?(:children_key)
|
124
|
+
o[:include_id] = true unless o.has_key?(:include_id)
|
125
|
+
o[:include_parent_id] = false unless o.has_key?(:include_parent_id)
|
126
|
+
o[:include_empty_children] = false unless o.has_key?(:include_empty_children)
|
127
|
+
o[:to_hash] = false unless o.has_key?(:to_hash)
|
128
|
+
|
129
|
+
res = Array.to_tree_children_loop(nil, self, o)
|
130
|
+
res = Array.to_tree_hash_loop(res, o) if o[:to_hash]
|
131
|
+
res
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
private
|
136
|
+
|
137
|
+
|
138
|
+
def self.to_tree_children_loop(parent_id, items, o)
|
139
|
+
res = []
|
140
|
+
|
141
|
+
items.select do |n|
|
142
|
+
(parent_id ? n[o[:parent_id_key]] == parent_id : n[o[:parent_id_key]].nil?)
|
143
|
+
end.each do |item|
|
144
|
+
new_item = {}
|
145
|
+
|
146
|
+
new_item[o[:id_key]] = item[o[:id_key]] if o[:to_hash] || o[:include_id]
|
147
|
+
new_item[o[:parent_id_key]] = parent_id if o[:to_hash] || o[:include_parent_id]
|
148
|
+
|
149
|
+
item.keys.reject do |key|
|
150
|
+
key == o[:id_key] || key == o[:parent_id_key]
|
151
|
+
end.each do |key|
|
152
|
+
new_item[key] = item[key]
|
153
|
+
end
|
154
|
+
|
155
|
+
children = Array.to_tree_children_loop(item[o[:id_key]], items, o)
|
156
|
+
|
157
|
+
if children.any? || (children.length == 0 && o[:include_empty_children])
|
158
|
+
new_item[o[:children_key]] = children
|
159
|
+
end
|
160
|
+
|
161
|
+
res << new_item
|
162
|
+
end
|
163
|
+
|
164
|
+
res
|
165
|
+
end
|
166
|
+
|
167
|
+
|
168
|
+
def self.to_tree_hash_loop(items, o)
|
169
|
+
res = {}
|
170
|
+
|
171
|
+
items.each do |item|
|
172
|
+
res = {}
|
173
|
+
id = item[o[:id_key]]
|
174
|
+
res[id] = {}
|
175
|
+
|
176
|
+
|
177
|
+
res[id][o[:id_key]] = item[o[:id_key]] if o[:include_id]
|
178
|
+
res[id][o[:parent_id_key]] = item[o[:parent_id_key]] if o[:include_parent_id]
|
179
|
+
|
180
|
+
item.keys.reject do |key|
|
181
|
+
(key == o[:id_key] || key == o[:parent_id_key])
|
182
|
+
end.each do |key|
|
183
|
+
res[id][key] = item[key]
|
184
|
+
end
|
185
|
+
|
186
|
+
if item[o[:children_key]]
|
187
|
+
res[id][o[:children_key]] = Array.to_tree_hash_loop(item[o[:children_key]], o)
|
188
|
+
else
|
189
|
+
res[id][o[:children_key]] = [] if o[:include_empty_children]
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
res
|
194
|
+
end
|
195
|
+
|
196
|
+
|
197
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class Hash
|
2
|
+
|
3
|
+
|
4
|
+
def deep_find(find_key)
|
5
|
+
Hash.deep_find_loop(self, [], find_key).flatten
|
6
|
+
end
|
7
|
+
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
|
12
|
+
def self.deep_find_loop(object, path, find_key)
|
13
|
+
found = []
|
14
|
+
|
15
|
+
if object.is_a?(Array)
|
16
|
+
object.each_with_index do |sub_object, index|
|
17
|
+
found << Hash.deep_find_loop(sub_object, path + [index], find_key)
|
18
|
+
end
|
19
|
+
elsif object.is_a?(Hash)
|
20
|
+
object.keys.each do |key|
|
21
|
+
found << {value: object[key], path: path + [key]} if key == find_key
|
22
|
+
found << Hash.deep_find_loop(object[key], path + [key], find_key)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
found
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module NumericRubyExtended
|
2
|
+
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.class_eval do
|
6
|
+
|
7
|
+
def no_zeros
|
8
|
+
self.to_f.to_s.gsub(/\.0+$/, '')
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_money
|
12
|
+
'%.2f' % self.to_f
|
13
|
+
end
|
14
|
+
|
15
|
+
def percent_of(percent, options = {})
|
16
|
+
result = (self.to_f / 100.to_f * percent.to_f)
|
17
|
+
options[:decimal] ? result : result.to_i
|
18
|
+
end
|
19
|
+
|
20
|
+
def get_percent_from(value, options = {})
|
21
|
+
result = (self.to_f / value.to_f * 100)
|
22
|
+
options[:decimal] ? result : result.to_i
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
class Integer
|
33
|
+
include NumericRubyExtended
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
class Float
|
38
|
+
include NumericRubyExtended
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
class BigDecimal
|
43
|
+
include NumericRubyExtended
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
class Complex
|
48
|
+
include NumericRubyExtended
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
class Rational
|
53
|
+
include NumericRubyExtended
|
54
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module ObjectRubyExtended
|
2
|
+
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.class_eval do
|
6
|
+
|
7
|
+
def dig(*items)
|
8
|
+
res, all_items = self, items.flatten
|
9
|
+
|
10
|
+
all_items.each do |item|
|
11
|
+
next if res.nil?
|
12
|
+
res = res[item] rescue nil
|
13
|
+
end
|
14
|
+
|
15
|
+
res
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
class Array
|
26
|
+
include ObjectRubyExtended
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
class Hash
|
31
|
+
include ObjectRubyExtended
|
32
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
class String
|
2
|
+
|
3
|
+
|
4
|
+
def strip_whitespace(options = {})
|
5
|
+
res = self
|
6
|
+
res = res.gsub("\u0020", '') # SPACE (U+0020)
|
7
|
+
res = res.gsub("\u00A0", '') # NO-BREAK SPACE (U+00A0)
|
8
|
+
res = res.gsub("\u1680", '') # OGHAM SPACE MARK (U+1680)
|
9
|
+
res = res.gsub("\u180E", '') # MONGOLIAN VOWEL SEPARATOR (U+180E)
|
10
|
+
res = res.gsub("\u2000", '') # EN QUAD (U+2000)
|
11
|
+
res = res.gsub("\u2002", '') # EN SPACE (nut) (U+2002)
|
12
|
+
res = res.gsub("\u2003", '') # EM SPACE (mutton) (U+2003)
|
13
|
+
res = res.gsub("\u2004", '') # THREE-PER-EM SPACE (thick space) (U+2004)
|
14
|
+
res = res.gsub("\u2005", '') # FOUR-PER-EM SPACE (mid space) (U+2005)
|
15
|
+
res = res.gsub("\u2006", '') # SIX-PER-EM SPACE (U+2006)
|
16
|
+
res = res.gsub("\u2007", '') # FIGURE SPACE (U+2007)
|
17
|
+
res = res.gsub("\u2008", '') # PUNCTUATION SPACE (U+2008)
|
18
|
+
res = res.gsub("\u2009", '') # THIN SPACE (U+2009)
|
19
|
+
res = res.gsub("\u200A", '') # HAIR SPACE (U+200A)
|
20
|
+
res = res.gsub("\u200B", '') # ZERO WIDTH SPACE (U+200B)
|
21
|
+
res = res.gsub("\u200F", '') # NARROW NO-BREAK SPACE (U+200F)
|
22
|
+
res = res.gsub("\u205F", '') # MEDIUM MATHEMATICAL SPACE (U+205F)
|
23
|
+
res = res.gsub("\u3000", '') # IDEOGRAPHIC SPACE (U+3000)
|
24
|
+
res = res.gsub("\uFEFF", '') # ZERO WIDTH NO-BREAK SPACE (U+FEFF)
|
25
|
+
|
26
|
+
if options[:visible]
|
27
|
+
res = res.gsub("\u2423", '') # OPEN BOX (U+2423)
|
28
|
+
res = res.gsub("\u2422", '') # BLANK SYMBOL (U+2422)
|
29
|
+
res = res.gsub("\u2420", '') # SYMBOL FOR SPACE (U+2420)
|
30
|
+
end
|
31
|
+
|
32
|
+
res
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
def strip_newline
|
37
|
+
res = self
|
38
|
+
res = res.delete("\n")
|
39
|
+
res = res.delete("\r")
|
40
|
+
res
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
def index_of(str)
|
45
|
+
res = []
|
46
|
+
self.scan(/#{str}/) { |c| res << [c, $~.offset(0)[0]] }
|
47
|
+
res.map(&:last)
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
def similarity_percent(b)
|
52
|
+
longer = [self.size, b.size].max
|
53
|
+
same = self.each_char.zip(b.each_char).select { |a, b| a == b }.size
|
54
|
+
percent = (longer - same) / self.size.to_f
|
55
|
+
(100.0 - (percent * 100.to_f))
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
end
|
data/readme.md
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# Ruby Extended
|
2
|
+
|
3
|
+

|
4
|
+

|
5
|
+
[](https://creativecommons.org/licenses/by/4.0/)
|
6
|
+
|
7
|
+
Extends ruby classes with useful methods.
|
8
|
+
|
9
|
+
## Documentation
|
10
|
+
Documentation [available here](/documentation/readme.md).
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
Add this line to your application's Gemfile:
|
14
|
+
```ruby
|
15
|
+
gem 'ruby_extended'
|
16
|
+
```
|
17
|
+
And then execute:
|
18
|
+
```bash
|
19
|
+
bundle
|
20
|
+
```
|
21
|
+
Or install it yourself as:
|
22
|
+
```bash
|
23
|
+
gem install ruby_extended
|
24
|
+
```
|
@@ -0,0 +1,24 @@
|
|
1
|
+
$:.push File.expand_path('../lib', __FILE__)
|
2
|
+
require 'ruby_extended/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = 'ruby_extended'
|
6
|
+
s.version = RubyExtended::VERSION.dup
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.authors = 'EdCordata'
|
9
|
+
s.description = 'Extend Ruby classes with helpful methods'
|
10
|
+
s.summary = 'Extend Ruby classes with helpful methods'
|
11
|
+
s.licenses = ['CC BY 4.0']
|
12
|
+
s.files = `git ls-files`.split("\n")
|
13
|
+
s.homepage = 'https://github.com/EdCordata-Ruby-Gems/ruby_extended'
|
14
|
+
s.metadata = {
|
15
|
+
'documentation_uri' => 'https://github.com/EdCordata-Ruby-Gems/ruby_extended/blob/master/documentation/readme.md',
|
16
|
+
'source_code_uri' => 'https://github.com/EdCordata-Ruby-Gems/ruby_extended',
|
17
|
+
'bug_tracker_uri' => 'https://github.com/EdCordata-Ruby-Gems/ruby_extended/issues',
|
18
|
+
'wiki_uri' => 'https://github.com/EdCordata-Ruby-Gems/ruby_extended/blob/master/documentation/readme.md',
|
19
|
+
}
|
20
|
+
s.require_paths = ['lib']
|
21
|
+
s.required_ruby_version = '>= 1.9.3'
|
22
|
+
s.rubygems_version = '1.6.2'
|
23
|
+
s.add_runtime_dependency 'unicode_utils', '~> 1'
|
24
|
+
end
|
@@ -0,0 +1,412 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bigdecimal'
|
4
|
+
require_relative '../lib/ruby_extended.rb'
|
5
|
+
|
6
|
+
RSpec.describe Array do
|
7
|
+
|
8
|
+
|
9
|
+
describe 'Array.sort_lv' do
|
10
|
+
|
11
|
+
it 'Should order Latvian special characters in array' do
|
12
|
+
expect(%w[a b ā c z č].sort_lv).to eql(%w[a ā b c č z])
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'Should order Latvian characters in array while accepting block' do
|
16
|
+
input_arr = [ { n: 'a' }, { n: 'c' }, { n: 'ā' }, { n: 'č' }, { n: 'z' } ]
|
17
|
+
output_arr = [ { n: 'a' }, { n: 'ā' }, { n: 'c' }, { n: 'č' }, { n: 'z' } ]
|
18
|
+
|
19
|
+
expect(input_arr.sort_lv { |x| x[:n] }).to eql(output_arr)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
describe 'Array.tabulate' do
|
26
|
+
input_arr = %w[a b c d e f g]
|
27
|
+
|
28
|
+
it 'Should return nil if tabulate value is 0' do
|
29
|
+
expect(input_arr.tabulate(0, split_by: :columns, direction: :horizontal)).to(be_nil)
|
30
|
+
expect(input_arr.tabulate(0, split_by: :rows, direction: :horizontal)).to(be_nil)
|
31
|
+
expect(input_arr.tabulate(0, split_by: :columns, direction: :vertical)).to(be_nil)
|
32
|
+
expect(input_arr.tabulate(0, split_by: :rows, direction: :vertical)).to(be_nil)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'Should return nil if tabulate value is bellow 1' do
|
36
|
+
expect(input_arr.tabulate(-1, split_by: :columns, direction: :horizontal)).to(be_nil)
|
37
|
+
expect(input_arr.tabulate(-1, split_by: :rows, direction: :horizontal)).to(be_nil)
|
38
|
+
expect(input_arr.tabulate(-1, split_by: :columns, direction: :vertical)).to(be_nil)
|
39
|
+
expect(input_arr.tabulate(-1, split_by: :rows, direction: :vertical)).to(be_nil)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'Should convert array to horizontal columns with value 2 (less as input)' do
|
43
|
+
output = [ ['a','b'], ['c','d'], ['e','f'], ['g',nil] ]
|
44
|
+
expect(input_arr.tabulate(2, split_by: :columns, direction: :horizontal)).to eql(output)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'Should convert array to horizontal rows with value 2 (less as input)' do
|
48
|
+
output = [ ['a','b','c','d'], ['e','f','g',nil] ]
|
49
|
+
expect(input_arr.tabulate(2, split_by: :rows, direction: :horizontal)).to eql(output)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'Should convert array to vertical columns with value 2 (less as input)' do
|
53
|
+
output = [ ['a','e'], ['b','f'], ['c','g'], ['d',nil] ]
|
54
|
+
expect(input_arr.tabulate(2, split_by: :columns, direction: :vertical)).to eql(output)
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'Should convert array to vertical rows with value 2 (less as input)' do
|
58
|
+
output = [ ['a','c','e','g'], ['b','d','f',nil] ]
|
59
|
+
expect(input_arr.tabulate(2, split_by: :rows, direction: :vertical)).to eql(output)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'Should convert array to horizontal columns with value 7 (same as input)' do
|
63
|
+
output = [ ['a','b','c','d','e','f','g'] ]
|
64
|
+
expect(input_arr.tabulate(7, split_by: :columns, direction: :horizontal)).to eql(output)
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'Should convert array to horizontal rows with value 7 (same as input)' do
|
68
|
+
output = [ ['a'],['b'],['c'],['d'],['e'],['f'],['g'] ]
|
69
|
+
expect(input_arr.tabulate(7, split_by: :rows, direction: :horizontal)).to eql(output)
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'Should convert array to horizontal columns with value 8 (more than input)' do
|
73
|
+
output = [ ['a','b','c','d','e','f','g', nil] ]
|
74
|
+
expect(input_arr.tabulate(8, split_by: :columns, direction: :horizontal)).to eql(output)
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'Should convert array to horizontal rows with value 8 (more than input)' do
|
78
|
+
output = [ ['a'],['b'],['c'],['d'],['e'],['f'],['g'], [nil] ]
|
79
|
+
expect(input_arr.tabulate(8, split_by: :rows, direction: :horizontal)).to eql(output)
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'Should convert array to horizontal columns with value 9 (more than input)' do
|
83
|
+
output = [ ['a','b','c','d','e','f','g', nil, nil] ]
|
84
|
+
expect(input_arr.tabulate(9, split_by: :columns, direction: :horizontal)).to eql(output)
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'Should convert array to horizontal rows with value 9 (more than input)' do
|
88
|
+
output = [ ['a'],['b'],['c'],['d'],['e'],['f'],['g'], [nil], [nil] ]
|
89
|
+
expect(input_arr.tabulate(9, split_by: :rows, direction: :horizontal)).to eql(output)
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
describe 'Array.sample_index' do
|
96
|
+
input_arr = %w[a b c d e f g h]
|
97
|
+
|
98
|
+
it 'Should return random index' do
|
99
|
+
expect(input_arr.sample_index(1).class).to be(Integer)
|
100
|
+
|
101
|
+
expect(input_arr.sample_index(1)).to(
|
102
|
+
be_between(0, (input_arr.length - 1))
|
103
|
+
)
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'Should return two random indexes' do
|
107
|
+
expect(input_arr.sample_index(2)).to be_instance_of(Array)
|
108
|
+
|
109
|
+
expect(input_arr.sample_index(2).length).to be(2)
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
describe 'Array.uniq_by_key' do
|
116
|
+
input_arr = [ {a: 1, b: '123'}, {a: 1, b: 'abc'}, {a: 2, b: 'cde'} ]
|
117
|
+
output_arr = [ {a: 1, b: '123'}, {a: 2, b: 'cde'} ]
|
118
|
+
|
119
|
+
it 'Should return uniq hash items' do
|
120
|
+
expect(input_arr.uniq_by_key(:a)).to eql(output_arr)
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'Should return original array if key not found' do
|
124
|
+
expect(input_arr.uniq_by_key(:x)).to eql(input_arr)
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
describe 'Array.duplicates' do
|
131
|
+
input_arr = ['a', 'a', 2, 2, 2, 2, 3, 'b', nil, nil]
|
132
|
+
|
133
|
+
it 'Should return array of duplicates' do
|
134
|
+
expect(input_arr.duplicates).to eql(['a', 2, nil])
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'Should return hash with duplicates and count' do
|
138
|
+
expect(input_arr.duplicates(full: true)).to(
|
139
|
+
eql([
|
140
|
+
{item: 'a', count: 2},
|
141
|
+
{item: 2, count: 4},
|
142
|
+
{item: nil, count: 2}
|
143
|
+
])
|
144
|
+
)
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
|
150
|
+
describe 'Array.sum' do
|
151
|
+
|
152
|
+
it 'Should sum array of integers' do
|
153
|
+
expect( [1, 2, 3].sum ).to eq(6)
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'Should sum array if floats' do
|
157
|
+
expect( [0.1, 0.2, 1].sum ).to eq(1.3)
|
158
|
+
end
|
159
|
+
|
160
|
+
it 'Should sum array of integers, floats and strings' do
|
161
|
+
expect( %w[a b].sum ).to eq('ab')
|
162
|
+
expect( ['a', 'b', 2, 1.5, nil].sum ).to eq('ab21.5')
|
163
|
+
end
|
164
|
+
|
165
|
+
it 'Should sum hash by keys' do
|
166
|
+
expect( [ {a: 1}, {a: 'a'}, {a: 3} ].sum(key: :a) ).to eq('1a3')
|
167
|
+
expect( [ {a: 1}, {a: 'a'}, {b: 3} ].sum(key: :a) ).to eq('1a')
|
168
|
+
expect( [ {a: 1}, {a: 2}, {b: 3} ].sum(key: :a) ).to eq(3)
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'Should recognize Float, Integer, BigDecimal, Complex and Rational' do
|
172
|
+
expect( [BigDecimal(1), Float(1), Integer(1), Complex(1), Rational(1)].sum ).to eq(5)
|
173
|
+
expect( [BigDecimal(1), Float(1), Integer(1), Complex(1), Rational(1), 'a'].sum(only_numbers: true) ).to eq(5)
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'Should sum only the number values if :only_numbers option provided' do
|
177
|
+
expect( ['a', 'b', 5].sum(only_numbers: true) ).to eq(5)
|
178
|
+
expect( ['a', 1, 1.5, nil].sum(only_numbers: true) ).to eq(2.5)
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'Should sum hash by keys, but only the number values if :only_numbers option provided' do
|
182
|
+
expect( [ {a: 1}, {a: 'a'}, {a: 3} ].sum(key: :a, only_numbers: true) ).to eq(4)
|
183
|
+
expect( [ {a: 1}, {a: 'a'}, {b: 3} ].sum(key: :a, only_numbers: true) ).to eq(1)
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'Should return nil if hash key was not found' do
|
187
|
+
expect( [ {a: 1}, {a: 'a'}, {a: 3} ].sum(key: :b) ).to be_nil
|
188
|
+
end
|
189
|
+
|
190
|
+
end
|
191
|
+
|
192
|
+
|
193
|
+
describe 'Array.to_tree' do
|
194
|
+
input_arr = [
|
195
|
+
{id: 1, parent_id: nil, any_other_key: 'a'},
|
196
|
+
{id: 2, parent_id: 1, any_other_key: 'b'},
|
197
|
+
{id: 3, parent_id: 2, any_other_key: 'c'},
|
198
|
+
]
|
199
|
+
|
200
|
+
input_arr_custom_keys = [
|
201
|
+
{id_x: 1, parent_id_x: nil, any_other_key: 'a'},
|
202
|
+
{id_x: 2, parent_id_x: 1, any_other_key: 'b'},
|
203
|
+
{id_x: 3, parent_id_x: 2, any_other_key: 'c'},
|
204
|
+
]
|
205
|
+
|
206
|
+
it 'Should convert array from using parent_id to array, using children sub-array' do
|
207
|
+
expect(input_arr.to_tree).to(
|
208
|
+
eq([
|
209
|
+
{
|
210
|
+
id: 1,
|
211
|
+
any_other_key: 'a',
|
212
|
+
children: [
|
213
|
+
{
|
214
|
+
id: 2,
|
215
|
+
any_other_key: 'b',
|
216
|
+
children: [ {id: 3, any_other_key: 'c'} ]
|
217
|
+
}
|
218
|
+
]
|
219
|
+
}
|
220
|
+
])
|
221
|
+
)
|
222
|
+
end
|
223
|
+
|
224
|
+
it 'Should convert array from using parent_id to array, using children sub-array but with custom keys' do
|
225
|
+
expect(input_arr_custom_keys.to_tree(id_key: :id_x, parent_id_key: :parent_id_x, children_key: :children_x)).to(
|
226
|
+
eq([
|
227
|
+
{
|
228
|
+
id_x: 1,
|
229
|
+
any_other_key: 'a',
|
230
|
+
children_x: [
|
231
|
+
{
|
232
|
+
id_x: 2,
|
233
|
+
any_other_key: 'b',
|
234
|
+
children_x: [
|
235
|
+
{id_x: 3, any_other_key: 'c'}
|
236
|
+
]
|
237
|
+
}
|
238
|
+
]
|
239
|
+
}
|
240
|
+
])
|
241
|
+
)
|
242
|
+
end
|
243
|
+
|
244
|
+
it 'Should convert array from using parent_id to array, using children sub-array but without id key' do
|
245
|
+
expect(input_arr.to_tree(include_id: false)).to(
|
246
|
+
eq([
|
247
|
+
{
|
248
|
+
any_other_key: 'a',
|
249
|
+
children: [
|
250
|
+
{
|
251
|
+
any_other_key: 'b',
|
252
|
+
children: [ {any_other_key: 'c'} ]
|
253
|
+
}
|
254
|
+
]
|
255
|
+
}
|
256
|
+
])
|
257
|
+
)
|
258
|
+
end
|
259
|
+
|
260
|
+
it 'Should convert array from using parent_id to array, using children sub-array but with parent_id key' do
|
261
|
+
expect(input_arr.to_tree(include_parent_id: true)).to(
|
262
|
+
eq([
|
263
|
+
{
|
264
|
+
id: 1,
|
265
|
+
any_other_key: 'a',
|
266
|
+
parent_id: nil,
|
267
|
+
children: [
|
268
|
+
{
|
269
|
+
id: 2,
|
270
|
+
any_other_key: 'b',
|
271
|
+
parent_id: 1,
|
272
|
+
children:
|
273
|
+
[ {id: 3, any_other_key: 'c', parent_id: 2} ]
|
274
|
+
}
|
275
|
+
]
|
276
|
+
}
|
277
|
+
])
|
278
|
+
)
|
279
|
+
end
|
280
|
+
|
281
|
+
it 'Should convert array from using parent_id to array, using children sub-array but with empty children key' do
|
282
|
+
expect(input_arr.to_tree(include_empty_children: true)).to(
|
283
|
+
eq([
|
284
|
+
{
|
285
|
+
id: 1,
|
286
|
+
any_other_key: 'a',
|
287
|
+
children:
|
288
|
+
[
|
289
|
+
{
|
290
|
+
id: 2,
|
291
|
+
any_other_key: 'b',
|
292
|
+
children:
|
293
|
+
[ {id: 3, any_other_key: 'c', children: []} ]
|
294
|
+
}
|
295
|
+
]
|
296
|
+
}
|
297
|
+
])
|
298
|
+
)
|
299
|
+
end
|
300
|
+
|
301
|
+
it 'Should convert array from using parent_id to hash, using children sub-array' do
|
302
|
+
expect(input_arr.to_tree(to_hash: true)).to(
|
303
|
+
eq({
|
304
|
+
1 => {
|
305
|
+
id: 1,
|
306
|
+
any_other_key: 'a',
|
307
|
+
children: {
|
308
|
+
2 => {
|
309
|
+
id: 2,
|
310
|
+
any_other_key: 'b',
|
311
|
+
children: {
|
312
|
+
3 => {id: 3, any_other_key: 'c'}
|
313
|
+
}
|
314
|
+
}
|
315
|
+
}
|
316
|
+
}
|
317
|
+
})
|
318
|
+
)
|
319
|
+
end
|
320
|
+
|
321
|
+
it 'Should convert array from using parent_id to hash, using children sub-array but with custom keys' do
|
322
|
+
expect(input_arr_custom_keys.to_tree(to_hash: true, id_key: :id_x, parent_id_key: :parent_id_x, children_key: :children_x)).to(
|
323
|
+
eq({
|
324
|
+
1 => {
|
325
|
+
id_x: 1,
|
326
|
+
any_other_key: 'a',
|
327
|
+
children_x: {
|
328
|
+
2 => {
|
329
|
+
id_x: 2,
|
330
|
+
any_other_key: 'b',
|
331
|
+
children_x: {
|
332
|
+
3 => {id_x: 3, any_other_key: 'c'}
|
333
|
+
}
|
334
|
+
}
|
335
|
+
}
|
336
|
+
}
|
337
|
+
})
|
338
|
+
)
|
339
|
+
end
|
340
|
+
|
341
|
+
it 'Should convert array from using parent_id to hash, using children sub-array but without id key' do
|
342
|
+
expect(input_arr.to_tree(to_hash: true, include_id: false)).to(
|
343
|
+
eq({
|
344
|
+
1 => {
|
345
|
+
any_other_key: 'a',
|
346
|
+
children: {
|
347
|
+
2 => {
|
348
|
+
any_other_key: 'b',
|
349
|
+
children: {
|
350
|
+
3 => {any_other_key: 'c'}
|
351
|
+
}
|
352
|
+
}
|
353
|
+
}
|
354
|
+
}
|
355
|
+
})
|
356
|
+
)
|
357
|
+
end
|
358
|
+
|
359
|
+
it 'Should convert array from using parent_id to hash, using children sub-array but with parent_id key' do
|
360
|
+
expect(input_arr.to_tree(to_hash: true, include_parent_id: true)).to(
|
361
|
+
eq({
|
362
|
+
1 => {
|
363
|
+
id: 1,
|
364
|
+
any_other_key: 'a',
|
365
|
+
parent_id: nil,
|
366
|
+
children: {
|
367
|
+
2 => {
|
368
|
+
id: 2,
|
369
|
+
any_other_key: 'b',
|
370
|
+
parent_id: 1,
|
371
|
+
children: {
|
372
|
+
3 => {
|
373
|
+
id: 3,
|
374
|
+
any_other_key: 'c',
|
375
|
+
parent_id: 2
|
376
|
+
}
|
377
|
+
}
|
378
|
+
}
|
379
|
+
}
|
380
|
+
}
|
381
|
+
})
|
382
|
+
)
|
383
|
+
end
|
384
|
+
|
385
|
+
it 'Should convert array from using parent_id to hash, using children sub-array but with empty children key' do
|
386
|
+
expect(input_arr.to_tree(to_hash: true, include_empty_children: true)).to(
|
387
|
+
eq({
|
388
|
+
1 => {
|
389
|
+
id: 1,
|
390
|
+
any_other_key: 'a',
|
391
|
+
children: {
|
392
|
+
2 => {
|
393
|
+
id: 2,
|
394
|
+
any_other_key: 'b',
|
395
|
+
children: {
|
396
|
+
3 => {
|
397
|
+
id: 3,
|
398
|
+
any_other_key: 'c',
|
399
|
+
children: {}
|
400
|
+
}
|
401
|
+
}
|
402
|
+
}
|
403
|
+
}
|
404
|
+
}
|
405
|
+
})
|
406
|
+
)
|
407
|
+
end
|
408
|
+
|
409
|
+
end
|
410
|
+
|
411
|
+
|
412
|
+
end
|