hash_base 0.1.6
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/.gitattributes +2 -0
- data/.gitignore +8 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/LICENSE +339 -0
- data/README.md +34 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/hash_base-0.1.5.gem +0 -0
- data/hash_base.gemspec +34 -0
- data/lib/hash_base/array/grouping.rb +97 -0
- data/lib/hash_base/array/to_html.rb +95 -0
- data/lib/hash_base/array/to_list.rb +48 -0
- data/lib/hash_base/array/to_text.rb +50 -0
- data/lib/hash_base/hash/apply.rb +65 -0
- data/lib/hash_base/hash/deep_values.rb +89 -0
- data/lib/hash_base/hash/grouping.rb +69 -0
- data/lib/hash_base/hash/to_table.rb +123 -0
- data/lib/hash_base/hash/zip_out.rb +58 -0
- data/lib/hash_base/version.rb +24 -0
- data/lib/hash_base.rb +31 -0
- metadata +84 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
#
|
|
3
|
+
# utilities for ruby hashes and ruby arrays
|
|
4
|
+
#
|
|
5
|
+
# Copyright © 2021 Stephan Wenzel <stephan.wenzel@drwpatent.de>
|
|
6
|
+
#
|
|
7
|
+
# This program is free software; you can redistribute it and/or
|
|
8
|
+
# modify it under the terms of the GNU General Public License
|
|
9
|
+
# as published by the Free Software Foundation; either version 2
|
|
10
|
+
# of the License, or (at your option) any later version.
|
|
11
|
+
#
|
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
# GNU General Public License for more details.
|
|
16
|
+
#
|
|
17
|
+
# You should have received a copy of the GNU General Public License
|
|
18
|
+
# along with this program; if not, write to the Free Software
|
|
19
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
20
|
+
#
|
|
21
|
+
|
|
22
|
+
class Array
|
|
23
|
+
|
|
24
|
+
########################################################################################
|
|
25
|
+
#
|
|
26
|
+
# to_html: creates a html table from a rectangular array
|
|
27
|
+
#
|
|
28
|
+
# options: headings: true/false, footer: true/false
|
|
29
|
+
#
|
|
30
|
+
########################################################################################
|
|
31
|
+
def to_html(options={}, &block)
|
|
32
|
+
|
|
33
|
+
options[:table] = options[:table].to_h.merge({:class => options[:table_class]}.compact) # support legacy
|
|
34
|
+
|
|
35
|
+
t = dup
|
|
36
|
+
body = t
|
|
37
|
+
head, body = [t.shift, t] if options[:headings]
|
|
38
|
+
foot, body = [t.pop , t] if options[:footer]
|
|
39
|
+
|
|
40
|
+
html_tag(:table, options[:table].to_h.compact) do
|
|
41
|
+
[head].compact.table_row_group(options.merge(:row_group => {:type => :thead}, :cell => {:type => :th}), &block) +
|
|
42
|
+
body.compact.table_row_group(options.merge(:row_group => {:type => :tbody}, :cell => {:type => :td}), &block) +
|
|
43
|
+
[foot].compact.table_row_group(options.merge(:row_group => {:type => :tfoot}, :cell => {:type => :td}), &block)
|
|
44
|
+
end
|
|
45
|
+
end #def
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def table_row_group(options={}, &block)
|
|
49
|
+
rows = collect.with_index do |row, row_index|
|
|
50
|
+
row.table_row(row_index, options, &block)
|
|
51
|
+
end.join("")
|
|
52
|
+
rows.present? ? html_tag(options.dig(:row_group, :type) || :tbody, rows) : ""
|
|
53
|
+
end #def
|
|
54
|
+
|
|
55
|
+
def table_row(row_index, options={}, &block)
|
|
56
|
+
html_tag(:tr, options[:row].to_h.compact) do
|
|
57
|
+
row = collect.with_index do |value, column_index|
|
|
58
|
+
html_tag(options.dig(:cell, :type) || :td, options[:cell].to_h.except(:type).compact) do
|
|
59
|
+
cell_value = if block_given?
|
|
60
|
+
yield value, column_index, row_index
|
|
61
|
+
else
|
|
62
|
+
style_value(value, options)
|
|
63
|
+
end
|
|
64
|
+
end #html_tag #cell_type
|
|
65
|
+
end.join("") #collect columns
|
|
66
|
+
row
|
|
67
|
+
end #html_tag #tr
|
|
68
|
+
end #def
|
|
69
|
+
|
|
70
|
+
########################################################################################
|
|
71
|
+
private
|
|
72
|
+
########################################################################################
|
|
73
|
+
def style_value(value, options={}, &block)
|
|
74
|
+
case value.class
|
|
75
|
+
when Integer
|
|
76
|
+
value.to_s
|
|
77
|
+
when Numeric
|
|
78
|
+
p = options[:precision] || 2
|
|
79
|
+
sprintf("%.#{p}f",value)
|
|
80
|
+
else
|
|
81
|
+
options[:html_safe] ? value.to_s : CGI::escapeHTML(value.to_s)
|
|
82
|
+
end
|
|
83
|
+
end #def
|
|
84
|
+
|
|
85
|
+
def html_tag(type, *content, &block)
|
|
86
|
+
if block_given?
|
|
87
|
+
opts = content.first.to_h.map{|k,v| " #{k}='#{v}'"}.join
|
|
88
|
+
"<#{type}#{opts}>#{yield block}</#{type}>"
|
|
89
|
+
else
|
|
90
|
+
opts = content[1].to_h.map{|k,v| " #{k}='#{v}'"}.join
|
|
91
|
+
"<#{type}#{opts}>#{content.first}</#{type}>"
|
|
92
|
+
end
|
|
93
|
+
end #def
|
|
94
|
+
|
|
95
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
#
|
|
3
|
+
# utilities for ruby hashes and ruby arrays
|
|
4
|
+
#
|
|
5
|
+
# Copyright © 2021 Stephan Wenzel <stephan.wenzel@drwpatent.de>
|
|
6
|
+
#
|
|
7
|
+
# This program is free software; you can redistribute it and/or
|
|
8
|
+
# modify it under the terms of the GNU General Public License
|
|
9
|
+
# as published by the Free Software Foundation; either version 2
|
|
10
|
+
# of the License, or (at your option) any later version.
|
|
11
|
+
#
|
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
# GNU General Public License for more details.
|
|
16
|
+
#
|
|
17
|
+
# You should have received a copy of the GNU General Public License
|
|
18
|
+
# along with this program; if not, write to the Free Software
|
|
19
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
20
|
+
#
|
|
21
|
+
|
|
22
|
+
class Array
|
|
23
|
+
|
|
24
|
+
########################################################################################
|
|
25
|
+
#
|
|
26
|
+
# converts array of hashes to one hash with elements in array
|
|
27
|
+
#
|
|
28
|
+
########################################################################################
|
|
29
|
+
class ArrayRowIsNotAHash < StandardError; end
|
|
30
|
+
|
|
31
|
+
def to_list
|
|
32
|
+
# test, if each element is a hash
|
|
33
|
+
each do |hash|
|
|
34
|
+
raise ArrayRowIsNotAHash unless hash.is_a?(Hash)
|
|
35
|
+
end
|
|
36
|
+
# extract all keys from all hashes
|
|
37
|
+
keys = map do |hash|
|
|
38
|
+
hash.keys
|
|
39
|
+
end.flatten.uniq
|
|
40
|
+
# now extract value for each key in each hash
|
|
41
|
+
map do |hash|
|
|
42
|
+
keys.map do |key|
|
|
43
|
+
hash[key]
|
|
44
|
+
end
|
|
45
|
+
end.unshift(keys)
|
|
46
|
+
end #def
|
|
47
|
+
|
|
48
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
#
|
|
3
|
+
# utilities for ruby hashes and ruby arrays
|
|
4
|
+
#
|
|
5
|
+
# Copyright © 2021 Stephan Wenzel <stephan.wenzel@drwpatent.de>
|
|
6
|
+
#
|
|
7
|
+
# This program is free software; you can redistribute it and/or
|
|
8
|
+
# modify it under the terms of the GNU General Public License
|
|
9
|
+
# as published by the Free Software Foundation; either version 2
|
|
10
|
+
# of the License, or (at your option) any later version.
|
|
11
|
+
#
|
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
# GNU General Public License for more details.
|
|
16
|
+
#
|
|
17
|
+
# You should have received a copy of the GNU General Public License
|
|
18
|
+
# along with this program; if not, write to the Free Software
|
|
19
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
20
|
+
#
|
|
21
|
+
|
|
22
|
+
class Array
|
|
23
|
+
|
|
24
|
+
########################################################################################
|
|
25
|
+
#
|
|
26
|
+
# creates a table from a rectangular array, balanced with indent
|
|
27
|
+
#
|
|
28
|
+
# indent: (Integer) number of spaces for padding each table element
|
|
29
|
+
# precision (Integer) number of precision digits to print for floats
|
|
30
|
+
# padding (String) string between adjacing colums
|
|
31
|
+
########################################################################################
|
|
32
|
+
def to_text(indent: 15, precision: 2, padding: " | " )
|
|
33
|
+
map do |line|
|
|
34
|
+
ln = line.is_a?(Array) ? line : [line]
|
|
35
|
+
ln.map do |e|
|
|
36
|
+
case e
|
|
37
|
+
when Integer
|
|
38
|
+
e.to_s.rjust(indent)
|
|
39
|
+
when Complex, Rational
|
|
40
|
+
e.to_s.rjust(indent)
|
|
41
|
+
when Numeric
|
|
42
|
+
sprintf("%.#{precision}f",e).rjust(indent)
|
|
43
|
+
else
|
|
44
|
+
e.to_s.ljust(indent)
|
|
45
|
+
end
|
|
46
|
+
end.join(padding)
|
|
47
|
+
end.join("\n")
|
|
48
|
+
end #def
|
|
49
|
+
|
|
50
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
#
|
|
3
|
+
# utilities for ruby hashes
|
|
4
|
+
#
|
|
5
|
+
# Copyright © 2021 Stephan Wenzel <stephan.wenzel@drwpatent.de>
|
|
6
|
+
#
|
|
7
|
+
# This program is free software; you can redistribute it and/or
|
|
8
|
+
# modify it under the terms of the GNU General Public License
|
|
9
|
+
# as published by the Free Software Foundation; either version 2
|
|
10
|
+
# of the License, or (at your option) any later version.
|
|
11
|
+
#
|
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
# GNU General Public License for more details.
|
|
16
|
+
#
|
|
17
|
+
# You should have received a copy of the GNU General Public License
|
|
18
|
+
# along with this program; if not, write to the Free Software
|
|
19
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
20
|
+
#
|
|
21
|
+
|
|
22
|
+
class Hash
|
|
23
|
+
|
|
24
|
+
########################################################################################
|
|
25
|
+
#
|
|
26
|
+
# apply(&block): applies block to deepest element, which is not a Hash
|
|
27
|
+
#
|
|
28
|
+
# -> hash
|
|
29
|
+
# new hash ->
|
|
30
|
+
#
|
|
31
|
+
########################################################################################
|
|
32
|
+
def apply( &block )
|
|
33
|
+
return to_enum(:each) unless block_given?
|
|
34
|
+
hash = Hash.new
|
|
35
|
+
each do |key, value|
|
|
36
|
+
if value.is_a?(Hash)
|
|
37
|
+
hash[key] = value.apply( &block )
|
|
38
|
+
else
|
|
39
|
+
hash[key] = yield value
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
hash
|
|
43
|
+
end #def
|
|
44
|
+
|
|
45
|
+
########################################################################################
|
|
46
|
+
#
|
|
47
|
+
# apply!(&block): applies block to deepest element, which is not a Hash
|
|
48
|
+
#
|
|
49
|
+
# -> hash
|
|
50
|
+
# same hash ->
|
|
51
|
+
#
|
|
52
|
+
########################################################################################
|
|
53
|
+
def apply!( &block )
|
|
54
|
+
return to_enum(:each) unless block_given?
|
|
55
|
+
each do |key, value|
|
|
56
|
+
if value.is_a?(Hash)
|
|
57
|
+
self[key] = value.apply( &block )
|
|
58
|
+
else
|
|
59
|
+
self[key] = yield value
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
self
|
|
63
|
+
end #def
|
|
64
|
+
|
|
65
|
+
end
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
#
|
|
3
|
+
# utilities for ruby hashes
|
|
4
|
+
#
|
|
5
|
+
# Copyright © 2021 Stephan Wenzel <stephan.wenzel@drwpatent.de>
|
|
6
|
+
#
|
|
7
|
+
# This program is free software; you can redistribute it and/or
|
|
8
|
+
# modify it under the terms of the GNU General Public License
|
|
9
|
+
# as published by the Free Software Foundation; either version 2
|
|
10
|
+
# of the License, or (at your option) any later version.
|
|
11
|
+
#
|
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
# GNU General Public License for more details.
|
|
16
|
+
#
|
|
17
|
+
# You should have received a copy of the GNU General Public License
|
|
18
|
+
# along with this program; if not, write to the Free Software
|
|
19
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
20
|
+
#
|
|
21
|
+
|
|
22
|
+
class Hash
|
|
23
|
+
|
|
24
|
+
########################################################################################
|
|
25
|
+
#
|
|
26
|
+
# deep_values: gets an array of values of a nested hash as a flat array
|
|
27
|
+
#
|
|
28
|
+
# -> hash
|
|
29
|
+
# array ->
|
|
30
|
+
#
|
|
31
|
+
########################################################################################
|
|
32
|
+
def deep_values
|
|
33
|
+
arr = Array.new
|
|
34
|
+
each do |key, value|
|
|
35
|
+
if value.is_a?(Hash)
|
|
36
|
+
arr += value.deep_values
|
|
37
|
+
else
|
|
38
|
+
arr << value
|
|
39
|
+
end
|
|
40
|
+
end #each
|
|
41
|
+
arr
|
|
42
|
+
end #def
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
########################################################################################
|
|
46
|
+
#
|
|
47
|
+
# max_depth: gets max depth of a hash
|
|
48
|
+
#
|
|
49
|
+
# -> hash
|
|
50
|
+
# int ->
|
|
51
|
+
#
|
|
52
|
+
########################################################################################
|
|
53
|
+
def max_depth(depth: 1)
|
|
54
|
+
max_depth = depth
|
|
55
|
+
each do |k,v|
|
|
56
|
+
if v.is_a?(Hash)
|
|
57
|
+
max_depth = [max_depth, v.max_depth( depth: depth + 1 )].max
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
max_depth
|
|
61
|
+
end #def
|
|
62
|
+
|
|
63
|
+
########################################################################################
|
|
64
|
+
#
|
|
65
|
+
# deep_diff: compares two hashes - counter part to Array.deep_diff
|
|
66
|
+
# source: stackoverflow
|
|
67
|
+
#
|
|
68
|
+
########################################################################################
|
|
69
|
+
def deep_diff(other, &block)
|
|
70
|
+
(self.keys + other.keys).uniq.inject({}) do |memo, key|
|
|
71
|
+
left = self[key]
|
|
72
|
+
right = other[key]
|
|
73
|
+
|
|
74
|
+
if block_given?
|
|
75
|
+
next memo if yield left, right
|
|
76
|
+
else
|
|
77
|
+
next memo if left == right
|
|
78
|
+
end
|
|
79
|
+
if left.respond_to?(:deep_diff) && right.respond_to?(:deep_diff)
|
|
80
|
+
memo[key] = left.deep_diff(right)
|
|
81
|
+
else
|
|
82
|
+
memo[key] = [left, right]
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
memo
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
#
|
|
3
|
+
# utilities for ruby hashes and ruby arrays
|
|
4
|
+
#
|
|
5
|
+
# Copyright © 2021 Stephan Wenzel <stephan.wenzel@drwpatent.de>
|
|
6
|
+
#
|
|
7
|
+
# This program is free software; you can redistribute it and/or
|
|
8
|
+
# modify it under the terms of the GNU General Public License
|
|
9
|
+
# as published by the Free Software Foundation; either version 2
|
|
10
|
+
# of the License, or (at your option) any later version.
|
|
11
|
+
#
|
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
# GNU General Public License for more details.
|
|
16
|
+
#
|
|
17
|
+
# You should have received a copy of the GNU General Public License
|
|
18
|
+
# along with this program; if not, write to the Free Software
|
|
19
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
20
|
+
#
|
|
21
|
+
|
|
22
|
+
class Hash
|
|
23
|
+
|
|
24
|
+
########################################################################################
|
|
25
|
+
#
|
|
26
|
+
# group_by_positions: counter part to Array.group_by_positions
|
|
27
|
+
#
|
|
28
|
+
# will only be invoked by Array.group_by_positions
|
|
29
|
+
#
|
|
30
|
+
########################################################################################
|
|
31
|
+
def group_by_positions( *positions )
|
|
32
|
+
ohash = ActiveSupport::OrderedHash.new
|
|
33
|
+
each do |key, val|
|
|
34
|
+
case val
|
|
35
|
+
when Hash, Array
|
|
36
|
+
ohash[key] = val.group_by_positions( *positions )
|
|
37
|
+
else
|
|
38
|
+
ohash[key] = val
|
|
39
|
+
end
|
|
40
|
+
end #each
|
|
41
|
+
ohash
|
|
42
|
+
end #def
|
|
43
|
+
|
|
44
|
+
########################################################################################
|
|
45
|
+
#
|
|
46
|
+
# expand: reverse of group_by_positions
|
|
47
|
+
#
|
|
48
|
+
# -> nested_hash
|
|
49
|
+
# -> array
|
|
50
|
+
#
|
|
51
|
+
########################################################################################
|
|
52
|
+
def expand(path_to_here=[])
|
|
53
|
+
arry = []
|
|
54
|
+
each do |k, v|
|
|
55
|
+
if v.is_a?(Hash)
|
|
56
|
+
arry += v.expand(path_to_here + [k])
|
|
57
|
+
elsif v.is_a?(Array)
|
|
58
|
+
v.each do |el|
|
|
59
|
+
arry << (path_to_here + [k] + el ) if el.is_a?(Array)
|
|
60
|
+
arry << (path_to_here + [k] + [el] ) unless el.is_a?(Array)
|
|
61
|
+
end
|
|
62
|
+
else
|
|
63
|
+
arry << (path_to_here + [k] + [v])
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
arry
|
|
67
|
+
end #def
|
|
68
|
+
|
|
69
|
+
end
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
#
|
|
3
|
+
# utilities for ruby hashes and ruby arrays
|
|
4
|
+
#
|
|
5
|
+
# Copyright © 2021 Stephan Wenzel <stephan.wenzel@drwpatent.de>
|
|
6
|
+
#
|
|
7
|
+
# This program is free software; you can redistribute it and/or
|
|
8
|
+
# modify it under the terms of the GNU General Public License
|
|
9
|
+
# as published by the Free Software Foundation; either version 2
|
|
10
|
+
# of the License, or (at your option) any later version.
|
|
11
|
+
#
|
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
# GNU General Public License for more details.
|
|
16
|
+
#
|
|
17
|
+
# You should have received a copy of the GNU General Public License
|
|
18
|
+
# along with this program; if not, write to the Free Software
|
|
19
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
20
|
+
#
|
|
21
|
+
|
|
22
|
+
class Hash
|
|
23
|
+
|
|
24
|
+
########################################################################################
|
|
25
|
+
#
|
|
26
|
+
# to_table: creates a rectangular table from a nested hash
|
|
27
|
+
#
|
|
28
|
+
# -> hash
|
|
29
|
+
# array ->
|
|
30
|
+
#
|
|
31
|
+
# parameters
|
|
32
|
+
#
|
|
33
|
+
# level: (Integer) only used internally for recursive calls (do not use)
|
|
34
|
+
# indent: (Integer) number of spaces for padding each table element
|
|
35
|
+
# precision (Integer) number of precision digits for floats
|
|
36
|
+
# dosort; (Boolean) should each level of keys be sorted ?
|
|
37
|
+
# content: (String) "style" => creates a table of cell styles, else table
|
|
38
|
+
# of data
|
|
39
|
+
# format: (String) "text" - text output, balanced with indent parameter
|
|
40
|
+
# "html" - html output
|
|
41
|
+
# total: (Proc) "-> x {x.flatten.inject(:+)}" proc to create totals of
|
|
42
|
+
# arrays of deepest values
|
|
43
|
+
# total_caption (String) caption for total line
|
|
44
|
+
# grand_total (Proc) "-> x {x.depp_values.flatten.inject(:+)}" proc to
|
|
45
|
+
# create totals of arrays of deepest values
|
|
46
|
+
# grant_total_caption (string) caption for grand total line
|
|
47
|
+
#
|
|
48
|
+
########################################################################################
|
|
49
|
+
def to_table( level: 0, indent: 15, precision: 2, dosort: true, content: "data", format: nil, divisor: nil, total: nil, total_caption: "", grand_total: nil, grand_total_caption: "" )
|
|
50
|
+
|
|
51
|
+
arry = []
|
|
52
|
+
i = 0
|
|
53
|
+
|
|
54
|
+
h = dosort ? sort : self
|
|
55
|
+
|
|
56
|
+
h.each do |k, v|
|
|
57
|
+
|
|
58
|
+
first_line = Array.new( i > 0 ? level : 0) {""} + [k] unless content == "style"
|
|
59
|
+
first_line = Array.new( i > 0 ? level : 0) {|l| "empty level_#{l}"} + ["key level_#{level}"] if content == "style"
|
|
60
|
+
|
|
61
|
+
if v.is_a?(Hash)
|
|
62
|
+
lines = v.to_table(level: level + 1, content: content, indent: indent, dosort: dosort, divisor: divisor, total: total, total_caption: total_caption, grand_total: grand_total, grand_total_caption: grand_total_caption)
|
|
63
|
+
first_line += lines[0] # complement current line with last key
|
|
64
|
+
arry << first_line
|
|
65
|
+
arry += lines.drop(1) if lines.drop(1).present?
|
|
66
|
+
elsif v.is_a?(Array) #must be array
|
|
67
|
+
lines = []
|
|
68
|
+
v.each_with_index do |av, i|
|
|
69
|
+
elem = (av.is_a?(Array) ? av : [av])
|
|
70
|
+
lines << (Array.new( i > 0 ? level + 1 : 0) {""} + elem ) unless content == "style"
|
|
71
|
+
lines << (Array.new( i > 0 ? level + 1 : 0) {|l| "empty level_#{l}"} + Array.new(elem.length){"value level_#{level}"} ) if content == "style"
|
|
72
|
+
end
|
|
73
|
+
first_line += lines[0] # complement current line
|
|
74
|
+
arry << first_line
|
|
75
|
+
arry += lines.drop(1) if lines.drop(1).present?
|
|
76
|
+
|
|
77
|
+
max_len = arry.map{|r| r.length}.max
|
|
78
|
+
|
|
79
|
+
unless content == "style"
|
|
80
|
+
arry << (Array.new( max_len + 1) {divisor.to_s * indent} ) if total && divisor
|
|
81
|
+
arry << (["#{total_caption}"] + Array.new( max_len - 1) {""} + [total.yield(v)] ) if total
|
|
82
|
+
arry << (Array.new( max_len + 1) {""} ) if total && divisor
|
|
83
|
+
else
|
|
84
|
+
arry << (Array.new( max_len + 1) {|l| "divisor level_#{l}"} ) if total && divisor
|
|
85
|
+
arry << (["total_caption level_0"] + Array.new( max_len - 1) {|l| "empty level_#{l+1}"} + ["total level_#{level}"] ) if total
|
|
86
|
+
arry << (Array.new( max_len + 1) {|l| "empty level_#{l}"} ) if total && divisor
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
i+=1
|
|
90
|
+
end #each
|
|
91
|
+
|
|
92
|
+
if level == 0
|
|
93
|
+
|
|
94
|
+
max_len = arry.map{|r| r.length}.max
|
|
95
|
+
|
|
96
|
+
unless content == "style"
|
|
97
|
+
arry << (Array.new( max_len + 1 ) {divisor.to_s * indent} ) if grand_total && divisor
|
|
98
|
+
arry << (["#{grand_total_caption}"] + Array.new( max_len - 1 ) {""} + [grand_total.yield(self)] ) if grand_total
|
|
99
|
+
else
|
|
100
|
+
arry << (Array.new( max_len + 1) {"grand_total divisor"} ) if grand_total && divisor
|
|
101
|
+
arry << (["grand_total_caption level_0"] + Array.new( max_len - 1) {|l| "empty grand_total level_#{l+1}"} + ["grand_total"]) if grand_total
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
max_len = arry.map{|r| r.length}.max
|
|
106
|
+
|
|
107
|
+
arry.map!{|l| l += Array.new(max_len - l.length) {""} } unless content == "style"
|
|
108
|
+
arry.map!{|l| l += Array.new(max_len - l.length) {"empty padding"} } if content == "style"
|
|
109
|
+
|
|
110
|
+
if format == "text"
|
|
111
|
+
arry.to_text(indent: indent, precision: precision)
|
|
112
|
+
elsif format == "html"
|
|
113
|
+
arry.to_html( styles: self.to_table(content: "style", total: true, grand_total: true))
|
|
114
|
+
else
|
|
115
|
+
arry
|
|
116
|
+
end
|
|
117
|
+
else
|
|
118
|
+
arry
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
end #def
|
|
122
|
+
|
|
123
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
#
|
|
3
|
+
# utilities for ruby hashes
|
|
4
|
+
#
|
|
5
|
+
# Copyright © 2021 Stephan Wenzel <stephan.wenzel@drwpatent.de>
|
|
6
|
+
#
|
|
7
|
+
# This program is free software; you can redistribute it and/or
|
|
8
|
+
# modify it under the terms of the GNU General Public License
|
|
9
|
+
# as published by the Free Software Foundation; either version 2
|
|
10
|
+
# of the License, or (at your option) any later version.
|
|
11
|
+
#
|
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
# GNU General Public License for more details.
|
|
16
|
+
#
|
|
17
|
+
# You should have received a copy of the GNU General Public License
|
|
18
|
+
# along with this program; if not, write to the Free Software
|
|
19
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
20
|
+
#
|
|
21
|
+
|
|
22
|
+
class Hash
|
|
23
|
+
|
|
24
|
+
########################################################################################
|
|
25
|
+
#
|
|
26
|
+
# zip_out: puts elements into one zip file with keys as filenames
|
|
27
|
+
#
|
|
28
|
+
# -> hash
|
|
29
|
+
# zip ->
|
|
30
|
+
#
|
|
31
|
+
# depends on gem 'zip'
|
|
32
|
+
#
|
|
33
|
+
########################################################################################
|
|
34
|
+
def zip_out(&block)
|
|
35
|
+
|
|
36
|
+
return nil unless defined?(Zip)
|
|
37
|
+
|
|
38
|
+
zip_stream = Zip::OutputStream.write_buffer do |zip|
|
|
39
|
+
|
|
40
|
+
each do |key, obj|
|
|
41
|
+
zip.put_next_entry(key)
|
|
42
|
+
if block_given?
|
|
43
|
+
zip.write(yield obj)
|
|
44
|
+
else
|
|
45
|
+
zip.write(obj)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# important - rewind the steam
|
|
51
|
+
zip_stream.rewind
|
|
52
|
+
|
|
53
|
+
# read out zip contents
|
|
54
|
+
zip_stream.read
|
|
55
|
+
|
|
56
|
+
end #def
|
|
57
|
+
|
|
58
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
#
|
|
3
|
+
# deep_try works like try, but with an arbitrary long list of methods
|
|
4
|
+
#
|
|
5
|
+
# Copyright © 2021 Stephan Wenzel <stephan.wenzel@drwpatent.de>
|
|
6
|
+
#
|
|
7
|
+
# This program is free software; you can redistribute it and/or
|
|
8
|
+
# modify it under the terms of the GNU General Public License
|
|
9
|
+
# as published by the Free Software Foundation; either version 2
|
|
10
|
+
# of the License, or (at your option) any later version.
|
|
11
|
+
#
|
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
# GNU General Public License for more details.
|
|
16
|
+
#
|
|
17
|
+
# You should have received a copy of the GNU General Public License
|
|
18
|
+
# along with this program; if not, write to the Free Software
|
|
19
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
20
|
+
#
|
|
21
|
+
|
|
22
|
+
module HashBase
|
|
23
|
+
VERSION = "0.1.6"
|
|
24
|
+
end
|
data/lib/hash_base.rb
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
#
|
|
3
|
+
# utilities for ruby hashes and ruby arrays
|
|
4
|
+
#
|
|
5
|
+
# Copyright © 2021 Stephan Wenzel <stephan.wenzel@drwpatent.de>
|
|
6
|
+
#
|
|
7
|
+
# This program is free software; you can redistribute it and/or
|
|
8
|
+
# modify it under the terms of the GNU General Public License
|
|
9
|
+
# as published by the Free Software Foundation; either version 2
|
|
10
|
+
# of the License, or (at your option) any later version.
|
|
11
|
+
#
|
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
# GNU General Public License for more details.
|
|
16
|
+
#
|
|
17
|
+
# You should have received a copy of the GNU General Public License
|
|
18
|
+
# along with this program; if not, write to the Free Software
|
|
19
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
20
|
+
#
|
|
21
|
+
|
|
22
|
+
require "hash_base/hash/grouping"
|
|
23
|
+
require "hash_base/hash/apply"
|
|
24
|
+
require "hash_base/hash/deep_values"
|
|
25
|
+
require "hash_base/hash/to_table"
|
|
26
|
+
require "hash_base/hash/zip_out"
|
|
27
|
+
|
|
28
|
+
require "hash_base/array/grouping"
|
|
29
|
+
require "hash_base/array/to_html"
|
|
30
|
+
require "hash_base/array/to_list"
|
|
31
|
+
require "hash_base/array/to_text"
|