ruby_extended 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
![Ruby Version](badges/ruby.svg)
|
4
|
+
![Coverage](badges/coverage.svg)
|
5
|
+
[![License](badges/license.svg)](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
|