hash_pivot 0.1.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -1
- data/Gemfile.lock +1 -1
- data/README.md +160 -4
- data/hash_pivot.gemspec +2 -1
- data/lib/hash_pivot/table.rb +27 -10
- data/lib/hash_pivot/version.rb +1 -1
- data/lib/hash_pivot.rb +18 -2
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 871d8c1d4c6a26913eb825057ee2823b54e9919c5a8faceadc008064fd239243
|
4
|
+
data.tar.gz: 4a5c03ee17d1ab10a11873f5b56419de12fadeaa6a34695e8eb1d3fd48f0d93e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b4c7fcd39a18b07f16c8b7facaeb42fdb76969d42879a0c663789458f007692233c9cdb4d4cb6d685d17877b8688e2f17f431c263c8578e1aad67f9b18d56f57
|
7
|
+
data.tar.gz: 9fa1e4cb4becd504a2832dcdf5d221709340a23e39ea9c35d917f797949b1768833675fc8e8874b848bce572f0fd84377d4699de6fdd7829e3153413c216421f
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
-
## [0.1
|
3
|
+
## [0.3.1] - 2022-06-28
|
4
|
+
|
5
|
+
- Refactoring code
|
6
|
+
- Add document url
|
7
|
+
|
8
|
+
## [0.3.0] - 2022-06-26
|
9
|
+
|
10
|
+
- Replace Column with label if Hash is given for pivot_kinds.
|
11
|
+
- Update README for label replacing.
|
12
|
+
|
13
|
+
## [0.2.0] - 2022-06-26
|
14
|
+
|
15
|
+
- Add usage examples in README.
|
16
|
+
- Fix CHANGELOG.md url.
|
17
|
+
|
18
|
+
## [0.1.0] - 2022-06-26
|
4
19
|
|
5
20
|
- Initial release
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -2,9 +2,7 @@
|
|
2
2
|
|
3
3
|
# HashPivot
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
TODO: Delete this and the text above, and describe your gem
|
5
|
+
Pivot Array of Hash or Array of Struct or ActiveRecord::Relation.
|
8
6
|
|
9
7
|
## Installation
|
10
8
|
|
@@ -18,7 +16,165 @@ If bundler is not being used to manage dependencies, install the gem by executin
|
|
18
16
|
|
19
17
|
## Usage
|
20
18
|
|
21
|
-
|
19
|
+
### Pivot Array of Hash
|
20
|
+
|
21
|
+
#### Prepare data
|
22
|
+
|
23
|
+
Prepare Array of Hash.
|
24
|
+
|
25
|
+
id | role | team | age
|
26
|
+
-- | -- | -- | --
|
27
|
+
1 | guest | rabbit | 1
|
28
|
+
2 | guest | mouse | 2
|
29
|
+
3 | guest | rabbit | 3
|
30
|
+
4 | admin | mouse | 4
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
data = [
|
34
|
+
{ id: 1, role: 'guest', team: 'rabbit', age: 1 },
|
35
|
+
{ id: 2, role: 'guest', team: 'mouse', age: 2 },
|
36
|
+
{ id: 3, role: 'guest', team: 'rabbit', age: 3 },
|
37
|
+
{ id: 4, role: 'admin', team: 'mouse', age: 4 }
|
38
|
+
]
|
39
|
+
```
|
40
|
+
|
41
|
+
#### Basic usage
|
42
|
+
|
43
|
+
Grouping by `:role` and pivot in `:team`. Pivot column is `rabbit or mouse` .
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
HashPivot.pivot(data, :role, :team, %w[rabbit mouse])
|
47
|
+
|
48
|
+
# [{ :role => "guest",
|
49
|
+
# "rabbit" => [{ :id => 1, :role => "guest", :team => "rabbit", :age => 1 }, { :id => 3, :role => "guest", :team => "rabbit", :age => 3 }],
|
50
|
+
# "mouse" => [{ :id => 2, :role => "guest", :team => "mouse", :age => 2 }] },
|
51
|
+
# { :role => "admin", "rabbit" => [], "mouse" => [{ :id => 4, :role => "admin", :team => "mouse", :age => 4 }] }]
|
52
|
+
```
|
53
|
+
|
54
|
+
role | rabbit | mouse
|
55
|
+
-- | -- | --
|
56
|
+
guest | {1 guest rabbit 1} {3 guest rabbit 3} | {2 guest mouse 2}
|
57
|
+
admin | | {4 admin mouse 4}
|
58
|
+
|
59
|
+
Grouping by `:role` and pivot in `:team`.
|
60
|
+
|
61
|
+
Pivot column is nil. This means that pivot column is automatically configured.
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
HashPivot.pivot(data, :role, :team, nil)
|
65
|
+
|
66
|
+
# [{ :role => "guest",
|
67
|
+
# "rabbit" => [{ :id => 1, :role => "guest", :team => "rabbit", :age => 1 }, { :id => 3, :role => "guest", :team => "rabbit", :age => 3 }],
|
68
|
+
# "mouse" => [{ :id => 2, :role => "guest", :team => "mouse", :age => 2 }] },
|
69
|
+
# { :role => "admin", "mouse" => [{ :id => 4, :role => "admin", :team => "mouse", :age => 4 }] }]
|
70
|
+
```
|
71
|
+
|
72
|
+
#### Pivot with summarize.
|
73
|
+
|
74
|
+
Pivot data is summarized by block.
|
75
|
+
|
76
|
+
Age is summarized by block.
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
HashPivot.pivot(data, :role, :team, %w[rabbit mouse]) { |array| array.sum { |h| h[:age] } }
|
80
|
+
|
81
|
+
# [{ :role => "guest", "rabbit" => 4, "mouse" => 2 }, { :role => "admin", "rabbit" => 0, "mouse" => 4 }]
|
82
|
+
```
|
83
|
+
|
84
|
+
role | rabbit | mouse
|
85
|
+
-- | -- | --
|
86
|
+
guest | 4 | 2
|
87
|
+
admin | 0 | 4
|
88
|
+
|
89
|
+
#### Pivot with summarize and replacing label.
|
90
|
+
|
91
|
+
If you give Hash for pivot kinds like this, pivot data is summarized by block and replace with labels.
|
92
|
+
|
93
|
+
```ruby
|
94
|
+
pivot_kinds = { 'rabbit' => 'RABBIT AGE',
|
95
|
+
'mouse' => 'MOUSE AGE' }
|
96
|
+
```
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
HashPivot.pivot(data, :role, :team, pivot_kinds) { |array| array.sum { |h| h[:age] } }
|
100
|
+
|
101
|
+
# [{ :role => "guest", "RABBIT AGE" => 4, "MOUSE AGE" => 2 }, { :role => "admin", "RABBIT AGE" => 0, "MOUSE AGE" => 4 }]
|
102
|
+
```
|
103
|
+
|
104
|
+
role | RABBIT AGE | MOUSE AGE
|
105
|
+
-- | -- | --
|
106
|
+
guest | 4 | 2
|
107
|
+
admin | 0 | 4
|
108
|
+
|
109
|
+
### Pivot Array of Struct
|
110
|
+
|
111
|
+
#### Prepare data
|
112
|
+
|
113
|
+
Prepare Array of Struct.
|
114
|
+
|
115
|
+
```ruby
|
116
|
+
HashPivotUserStruct = Struct.new(:id, :role, :team, :age, keyword_init: true)
|
117
|
+
data = [
|
118
|
+
HashPivotUserStruct.new(id: 1, role: 'guest', team: 'rabbit', age: 1),
|
119
|
+
HashPivotUserStruct.new(id: 2, role: 'guest', team: 'mouse', age: 2),
|
120
|
+
HashPivotUserStruct.new({ id: 3, role: 'guest', team: 'rabbit', age: 3 }),
|
121
|
+
HashPivotUserStruct.new({ id: 4, role: 'admin', team: 'mouse', age: 4 })
|
122
|
+
]
|
123
|
+
```
|
124
|
+
|
125
|
+
#### Basic usage
|
126
|
+
|
127
|
+
Grouping by `:role` and pivot in `:team`. Pivot column is `rabbit or mouse` .
|
128
|
+
|
129
|
+
```ruby
|
130
|
+
HashPivot.pivot(data, :role, :team, %w[rabbit mouse], repository: HashPivot::Repository::StructRepository)
|
131
|
+
|
132
|
+
# [{ :role => "guest",
|
133
|
+
# "rabbit" => [{ :id => 1, :role => "guest", :team => "rabbit", :age => 1 }, { :id => 3, :role => "guest", :team => "rabbit", :age => 3 }],
|
134
|
+
# "mouse" => [{ :id => 2, :role => "guest", :team => "mouse", :age => 2 }] },
|
135
|
+
# { :role => "admin", "rabbit" => [], "mouse" => [{ :id => 4, :role => "admin", :team => "mouse", :age => 4 }] }]
|
136
|
+
```
|
137
|
+
|
138
|
+
|
139
|
+
### Pivot Array of ActiveRecord::Relation
|
140
|
+
|
141
|
+
#### Prepare data
|
142
|
+
|
143
|
+
Prepare Array of ActiveRecord::Relation.
|
144
|
+
|
145
|
+
```ruby
|
146
|
+
class MigrateSqlDatabase < ActiveRecord::Migration[6.1]
|
147
|
+
def self.up
|
148
|
+
create_table(:hash_pivot_users) do |t|
|
149
|
+
t.string :role
|
150
|
+
t.string :team
|
151
|
+
t.integer :age
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
```
|
156
|
+
|
157
|
+
```ruby
|
158
|
+
HashPivotUser.destroy_all
|
159
|
+
HashPivotUser.create(:hash_pivot_user, id: 1, role: 'guest', team: 'rabbit', age: 1)
|
160
|
+
HashPivotUser.create(:hash_pivot_user, id: 2, role: 'guest', team: 'mouse', age: 2)
|
161
|
+
HashPivotUser.create(:hash_pivot_user, id: 3, role: 'guest', team: 'rabbit', age: 3)
|
162
|
+
HashPivotUser.create(:hash_pivot_user, id: 4, role: 'admin', team: 'mouse', age: 4)
|
163
|
+
```
|
164
|
+
|
165
|
+
#### Basic usage
|
166
|
+
|
167
|
+
Grouping by `:role` and pivot in `:team`. Pivot column is `rabbit or mouse` .
|
168
|
+
|
169
|
+
```ruby
|
170
|
+
HashPivot.pivot(data, :role, :team, %w[rabbit mouse], repository: HashPivot::Repository::ActiveRecordRepository)
|
171
|
+
|
172
|
+
# [{ :role => "guest",
|
173
|
+
# "rabbit" => [{ :id => 1, :role => "guest", :team => "rabbit", :age => 1 }, { :id => 3, :role => "guest", :team => "rabbit", :age => 3 }],
|
174
|
+
# "mouse" => [{ :id => 2, :role => "guest", :team => "mouse", :age => 2 }] },
|
175
|
+
# { :role => "admin", "rabbit" => [], "mouse" => [{ :id => 4, :role => "admin", :team => "mouse", :age => 4 }] }]
|
176
|
+
```
|
177
|
+
|
22
178
|
|
23
179
|
## Development
|
24
180
|
|
data/hash_pivot.gemspec
CHANGED
@@ -16,7 +16,8 @@ Gem::Specification.new do |spec|
|
|
16
16
|
|
17
17
|
spec.metadata['homepage_uri'] = spec.homepage
|
18
18
|
spec.metadata['source_code_uri'] = spec.homepage
|
19
|
-
spec.metadata['changelog_uri'] = "#{spec.homepage}CHANGELOG.md"
|
19
|
+
spec.metadata['changelog_uri'] = "#{spec.homepage}/blob/main/CHANGELOG.md"
|
20
|
+
spec.metadata['documentation_uri'] = 'https://rubydoc.info/gems/hash_pivot'
|
20
21
|
|
21
22
|
# Specify which files should be added to the gem when it is released.
|
22
23
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
data/lib/hash_pivot/table.rb
CHANGED
@@ -6,34 +6,51 @@ require_relative './repository/struct_repository'
|
|
6
6
|
|
7
7
|
module HashPivot
|
8
8
|
class Table
|
9
|
+
# rubocop:disable Layout/LineLength
|
10
|
+
|
9
11
|
# @param [Array<Hash>] data
|
12
|
+
# @param [Class<HashPivot::Repository::HashRepository,HashPivot::Repository::StructRepository,HashPivot::Repository::ActiveRecordRepository>] repository
|
10
13
|
def initialize(data, repository: HashPivot::Repository::HashRepository)
|
11
14
|
@data = data
|
12
15
|
@repository = repository
|
13
16
|
end
|
14
17
|
|
18
|
+
# rubocop:enable Layout/LineLength
|
19
|
+
|
15
20
|
# @param [Array, Object] group
|
16
21
|
# @param [Object] pivot_in
|
17
|
-
# @param [
|
22
|
+
# @param [Hash,nil] pivot_kinds
|
23
|
+
# @param [Proc] block
|
24
|
+
# @return [Array<Hash>]
|
18
25
|
def pivot(group, pivot_in, pivot_kinds, &block)
|
19
26
|
group = [group] unless group.is_a?(Array)
|
20
27
|
@repository.hash_by_group(@data, group, pivot_in).each_with_object([]) do |(key, array), memo|
|
21
|
-
hash =
|
28
|
+
hash = transpose_with(pivot_kinds, array, pivot_in, &block)
|
22
29
|
|
23
30
|
memo << key.merge(hash)
|
24
31
|
end
|
25
32
|
end
|
26
33
|
|
27
|
-
|
28
|
-
|
29
|
-
|
34
|
+
private
|
35
|
+
|
36
|
+
# @param [Hash,nil] pivot_kinds
|
37
|
+
# @param [Array] array
|
38
|
+
# @param [Object] pivot_in
|
39
|
+
# @param [Proc] block
|
40
|
+
# @return [Hash]
|
41
|
+
def transpose_with(pivot_kinds, array, pivot_in, &block)
|
42
|
+
pivot_kinds ||= calculated_pivot_kinds_from(array, pivot_in)
|
43
|
+
pivot_kinds.each_with_object({}) do |(pivot_kind, pivot_label), memo|
|
30
44
|
pivoted_data = array.select { |h| h[pivot_in] == pivot_kind }
|
31
|
-
memo[
|
32
|
-
yield(pivoted_data)
|
33
|
-
else
|
34
|
-
pivoted_data
|
35
|
-
end
|
45
|
+
memo[pivot_label] = block ? yield(pivoted_data) : pivoted_data
|
36
46
|
end
|
37
47
|
end
|
48
|
+
|
49
|
+
# @param [Array] array
|
50
|
+
# @param [Object] pivot_in
|
51
|
+
# @return [Hash]
|
52
|
+
def calculated_pivot_kinds_from(array, pivot_in)
|
53
|
+
array.map { |h| h[pivot_in] }.uniq.compact.each_with_object({}) { |kind, memo| memo[kind] = kind }
|
54
|
+
end
|
38
55
|
end
|
39
56
|
end
|
data/lib/hash_pivot/version.rb
CHANGED
data/lib/hash_pivot.rb
CHANGED
@@ -4,12 +4,28 @@ require_relative 'hash_pivot/version'
|
|
4
4
|
require_relative 'hash_pivot/table'
|
5
5
|
require 'hash_pivot/error/not_implemented_error'
|
6
6
|
module HashPivot
|
7
|
+
# rubocop:disable Layout/LineLength
|
8
|
+
|
7
9
|
# @param [Array<Hash>] data
|
8
10
|
# @param [Array] group
|
9
11
|
# @param [Object] pivot_in
|
10
|
-
# @param [Array]
|
12
|
+
# @param [Array,Hash,nil] pivot_header
|
11
13
|
# @return [Hash]
|
12
|
-
|
14
|
+
# @param [Class<HashPivot::Repository::HashRepository,HashPivot::Repository::StructRepository,HashPivot::Repository::ActiveRecordRepository>] repository
|
15
|
+
# @param [Proc] block
|
16
|
+
def self.pivot(data, group, pivot_in, pivot_header, repository: HashPivot::Repository::HashRepository, &block)
|
17
|
+
pivot_kinds = if pivot_header.is_a?(Array)
|
18
|
+
transform_to_hash(pivot_header)
|
19
|
+
else
|
20
|
+
pivot_header
|
21
|
+
end
|
13
22
|
Table.new(data, repository: repository).pivot(group, pivot_in, pivot_kinds, &block)
|
14
23
|
end
|
24
|
+
|
25
|
+
# rubocop:enable Layout/LineLength
|
26
|
+
|
27
|
+
def self.transform_to_hash(array)
|
28
|
+
array.each_with_object({}) { |kind, memo| memo[kind] = kind }
|
29
|
+
end
|
30
|
+
private_class_method :transform_to_hash
|
15
31
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hash_pivot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- junara
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-06-
|
11
|
+
date: 2022-06-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -182,7 +182,8 @@ licenses:
|
|
182
182
|
metadata:
|
183
183
|
homepage_uri: https://github.com/junara/hash_pivot
|
184
184
|
source_code_uri: https://github.com/junara/hash_pivot
|
185
|
-
changelog_uri: https://github.com/junara/
|
185
|
+
changelog_uri: https://github.com/junara/hash_pivot/blob/main/CHANGELOG.md
|
186
|
+
documentation_uri: https://rubydoc.info/gems/hash_pivot
|
186
187
|
rubygems_mfa_required: 'true'
|
187
188
|
post_install_message:
|
188
189
|
rdoc_options: []
|