iteraptor 0.4.0 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0e8cc46b604659e350fd66dd26157c0a0810373c
4
- data.tar.gz: 10105442b0e2c0a807e55ff1decf52fbef0d5772
3
+ metadata.gz: 98397269de93f3ef4ade2c6910e602576ce96b10
4
+ data.tar.gz: c530c00a774a1f251aa7024d19861661a43ba4b2
5
5
  SHA512:
6
- metadata.gz: ff5aade1285567f7bf58d422316db68b3e42627c828c13ad54d6c1f533d7542b3c15ca666b8a0b33ff175e6f83363c17ad591c4b7351f031808019938c8e348f
7
- data.tar.gz: bd271aae4e66a0528f0efb9eba9b5e2bd0cc87082ffee878e5a134fc5bf57358f498cb968c9fce0d81dca90a0cc384f877d0252c97b0c191825cdebde7024502
6
+ metadata.gz: ead6d1ff57914ff11d3607ff0b31e580e7fdeaa0352aa1e4427c17e46a1997e90f1885a6576a7d85858e1dd21da945befa81d3aa827129a109b4cc8b5a8e8c0f
7
+ data.tar.gz: 31f7e4a9d26fabee622e5a9a997f1b7e1cad9e9df3a0a9a603b08cabf0cd3ce324b8da131706b548cee55383b15461e2320f23814decd51f1145ba63ca20f540
data/Gemfile CHANGED
@@ -3,4 +3,3 @@ source 'https://rubygems.org'
3
3
  # Specify your gem's dependencies in iteraptor.gemspec
4
4
  gemspec
5
5
  gem 'simplecov', require: false, group: :test
6
- # gem 'codeclimate-test-reporter', group: :test, require: nil
data/README.md CHANGED
@@ -38,8 +38,11 @@ element;
38
38
  whatever it is; `nil`s are not treated in some special way
39
39
  * `aplanar` (_sp._ `flatten`) the analogue of `Array#flatten`, but flattens
40
40
  the deep enumerable into `Hash` instance
41
+ * `recoger` (_sp._ `harvest`, `collect`) the opposite to `aplanar`, it builds
42
+ the nested structure out of flattened hash
41
43
  * `segar` (_sp._ `yield`), alias `escoger` (_sp._ `select`) allows to filter
42
- and collect elelements.
44
+ and collect elelements
45
+ * `rechazar` (_sp._ `reject`) allows to filter out and collect elelements.
43
46
 
44
47
  ### Iteration
45
48
 
data/iteraptor.gemspec CHANGED
@@ -25,7 +25,8 @@ Gem::Specification.new do |spec|
25
25
  spec.require_paths = ['lib']
26
26
 
27
27
  spec.add_development_dependency 'bundler', '~> 1'
28
- spec.add_development_dependency 'rake', '~> 10.0'
29
- spec.add_development_dependency 'rspec', '~> 3.0'
30
- spec.add_development_dependency 'pry', '~> 0.10'
28
+ spec.add_development_dependency 'rake', '~> 10'
29
+ spec.add_development_dependency 'rspec', '~> 3'
30
+ spec.add_development_dependency 'pry'
31
+ spec .add_development_dependency 'awesome_print'
31
32
  end
@@ -1,3 +1,3 @@
1
1
  module Iteraptor
2
- VERSION = '0.4.0'
2
+ VERSION = '0.5.0'
3
3
  end
data/lib/iteraptor.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  require "iteraptor/version"
2
2
 
3
+ # rubocop:disable Style/VariableNumber
4
+ # rubocop:disable Metrics/ModuleLength
3
5
  module Iteraptor
4
6
  DELIMITER = '.'.freeze
5
7
 
@@ -8,58 +10,65 @@ module Iteraptor
8
10
  end
9
11
 
10
12
  %i[cada mapa].each do |m|
11
- define_method m do |root = nil, parent = nil, &λ|
12
- return enum_for(m, root, parent) unless λ
13
+ define_method m do |root = nil, parent = nil, **params, &λ|
14
+ return enum_for(m, root, parent, **params) unless λ
15
+ return self if empty?
16
+
13
17
  send_to = [Hash, Array, Enumerable].detect(&method(:is_a?))
14
- send_to && send("#{m}_in_#{send_to.name.downcase}", root || self, parent, &λ)
18
+ send_to && send("#{m}_in_#{send_to.name.downcase}", root || self, parent, **params, &λ)
15
19
  end
16
20
  end
17
21
 
18
- # rubocop:disable Style/MultilineIfModifier
19
- # rubocop:disable Metrics/CyclomaticComplexity
20
- # rubocop:disable Metrics/MethodLength
21
- def segar filter
22
- return enum_for(:segar, filter) unless block_given?
23
-
24
- cada.with_object({}) do |(parent, element), memo|
25
- p = parent.split(DELIMITER)
26
- if case filter
27
- when String then p.include?(filter)
28
- when Symbol then p.include?(filter.to_s)
29
- when Regexp then p.any? { |key| key =~ filter }
30
- when Array then parent.include?(filter.map(&:to_s).join(DELIMITER))
31
- end
32
- yield parent, element
33
- memo[parent] = element
34
- end
35
- end
22
+ def rechazar *filter, **params
23
+ return self if empty?
24
+ rechazar_o_escoger false, *filter, **params
36
25
  end
37
26
 
38
- def aplanar delimiter: DELIMITER, symbolize_keys: false
27
+ def escoger *filter, **params
28
+ return self if empty?
29
+ rechazar_o_escoger true, *filter, **params
30
+ end
31
+
32
+ # rubocop:disable Style/Alias
33
+ alias_method :segar, :escoger
34
+ # rubocop:enable Style/Alias
35
+
36
+ def aplanar delimiter: DELIMITER, **params
37
+ return self if empty?
39
38
  cada.with_object({}) do |(parent, element), acc|
40
39
  key = parent.tr(DELIMITER, delimiter)
41
- key = key.to_sym if symbolize_keys
40
+ key = key.to_sym if params[:symbolize_keys]
42
41
  acc[key] = element unless element.is_a?(Enumerable)
43
42
  yield key, element if block_given?
44
43
  end
45
44
  end
46
45
 
47
- def plana_mapa delimiter: DELIMITER, symbolize_keys: false
48
- return enum_for(
49
- :plana_mapa, delimiter: delimiter, symbolize_keys: symbolize_keys
50
- ) unless block_given?
46
+ def recoger delimiter: DELIMITER, **params
47
+ return self if empty?
48
+ # rubocop:disable Style/MultilineBlockChain
49
+ aplanar.each_with_object(
50
+ Hash.new { |h, k| h[k] = h.clone.clear }
51
+ ) do |(k, v), acc|
52
+ keys = k.split(delimiter)
53
+ parent = keys[0..-2].reduce(acc){ |h, kk| h[kk] }
54
+ parent[keys.last] = v
55
+ end.mapa(yield_all: true, **params) do |_parent, (k, v)|
56
+ [k, v]
57
+ end
58
+ # rubocop:enable Style/MultilineBlockChain
59
+ end
60
+
61
+ def plana_mapa delimiter: DELIMITER, **params
62
+ return enum_for(:plana_mapa, delimiter: delimiter, **params) unless block_given?
63
+ return self if empty?
51
64
 
52
65
  cada.with_object([]) do |(parent, element), acc|
53
66
  key = parent.tr(DELIMITER, delimiter)
54
- key = key.to_sym if symbolize_keys
67
+ key = key.to_sym if params[:symbolize_keys]
55
68
  acc << yield(key, element) unless element.is_a?(Enumerable)
56
69
  end
57
70
  end
58
71
 
59
- # rubocop:enable Metrics/MethodLength
60
- # rubocop:enable Metrics/CyclomaticComplexity
61
- # rubocop:enable Style/MultilineIfModifier
62
-
63
72
  private
64
73
 
65
74
  ##############################################################################
@@ -71,7 +80,7 @@ module Iteraptor
71
80
  end
72
81
  end
73
82
 
74
- def cada_in_array root = nil, parent = nil
83
+ def cada_in_array root = nil, parent = nil, **_
75
84
  λ = Proc.new
76
85
  each.with_index do |e, idx|
77
86
  [parent, idx].compact.join(DELIMITER).tap do |p|
@@ -82,7 +91,7 @@ module Iteraptor
82
91
  end
83
92
  alias cada_in_enumerable cada_in_array
84
93
 
85
- def cada_in_hash root = nil, parent = nil
94
+ def cada_in_hash root = nil, parent = nil, **_
86
95
  λ = Proc.new
87
96
  each do |k, v|
88
97
  [parent, k].compact.join(DELIMITER).tap do |p|
@@ -94,33 +103,90 @@ module Iteraptor
94
103
 
95
104
  ##############################################################################
96
105
  ### mapa
97
- def mapa_in_array root = nil, parent = nil, with_index: false
106
+ # FIXME what happens if I return nil from mapa in array?
107
+ # Params:
108
+ # - with_index
109
+ # - yield_all
110
+ # - symbolize_keys
111
+ def mapa_in_array root = nil, parent = nil, **params
98
112
  λ = Proc.new
99
113
 
100
114
  map.with_index do |e, idx|
101
115
  p = [parent, idx].compact.join(DELIMITER)
102
116
 
117
+ e = yield p, (params[:with_index] ? [idx.to_s, e] : e) if !e.is_a?(Enumerable) || params[:yield_all]
118
+
103
119
  case e
104
- when Iteraptor then e.mapa(root, p, &λ)
120
+ when Iteraptor then e.mapa(root, p, **params, &λ)
105
121
  when Enumerable then e.map(&λ.curry[p])
106
- else yield p, (with_index ? [idx.to_s, e] : e)
122
+ else e
107
123
  end
108
124
  end
109
125
  end
110
126
  alias mapa_in_enumerable mapa_in_array
111
127
 
112
- def mapa_in_hash root = nil, parent = nil
128
+ # Params:
129
+ # - yield_all
130
+ # - symbolize_keys
131
+ def mapa_in_hash root = nil, parent = nil, **params
113
132
  λ = Proc.new
114
133
 
115
134
  map do |k, v|
116
135
  p = [parent, k].compact.join(DELIMITER)
117
136
 
137
+ k, v = yield p, [k, v] if !v.is_a?(Enumerable) || params[:yield_all]
138
+
118
139
  case v
119
- when Iteraptor then [k, v.mapa(root, p, &λ)]
140
+ when Iteraptor then [k, v.mapa(root, p, **params, &λ)]
120
141
  when Enumerable then [k, v.map(&λ.curry[p])]
121
- else yield p, [k, v]
142
+ else k.nil? ? nil : [k, v]
122
143
  end
123
- end.compact.to_h
144
+ end.compact.send(:to_hash_or_array, **params)
145
+ end
146
+
147
+ ##############################################################################
148
+ ### helpers
149
+ def safe_symbolize key
150
+ key.respond_to?(:to_sym) ? key.to_sym : key
151
+ end
152
+
153
+ def to_hash_or_array **params
154
+ # rubocop:disable Style/MultilineTernaryOperator
155
+ # rubocop:disable Style/RescueModifier
156
+ receiver =
157
+ is_a?(Array) &&
158
+ all? { |e| e.is_a?(Enumerable) && e.size == 2 } &&
159
+ map(&:first).uniq.size == size ? (to_h rescue self) : self
160
+ # rubocop:enable Style/RescueModifier
161
+
162
+ return receiver unless receiver.is_a?(Hash)
163
+ return receiver.values if receiver.keys.each_with_index.all? { |key, idx| key == idx.to_s }
164
+ return receiver unless params[:symbolize_keys]
165
+
166
+ receiver.map { |k, v| [safe_symbolize(k), v] }.to_h
167
+ # rubocop:enable Style/MultilineTernaryOperator
168
+ end
169
+
170
+ HASH_TO_ARRAY_ERROR_MSG = %(undefined method `hash_to_array?' for "%s":%s).freeze
171
+ def hash_to_hash_or_array
172
+ raise NoMethodError, HASH_TO_ARRAY_ERROR_MSG % [inspect, self.class] unless is_a?(Hash)
173
+ end
174
+
175
+ ##############################################################################
176
+ # filters
177
+ def rechazar_o_escoger method, *filter, **params
178
+ raise ArgumentError, "no filter given in call to #{method ? :escoger : :rechazar}" if filter.empty?
179
+
180
+ plough = method ? :none? : :any?
181
+ aplanar.each_with_object({}) do |(key, value), acc|
182
+ to_match = key.split(DELIMITER)
183
+ to_match = to_match.flat_map { |k| [k.to_s, k.to_s.to_sym] } if params[:soft_keys]
184
+
185
+ next if filter.public_send(plough, &->(f){ to_match.any?(&f.method(:===)) })
186
+
187
+ value = yield key, value if block_given?
188
+ acc[key] = value
189
+ end.recoger(**params)
124
190
  end
125
191
 
126
192
  ##############################################################################
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: iteraptor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aleksei Matiushkin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-03-28 00:00:00.000000000 Z
11
+ date: 2018-03-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -30,42 +30,56 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: '10'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: '10'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '3.0'
47
+ version: '3'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '3.0'
54
+ version: '3'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: pry
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '0.10'
61
+ version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: awesome_print
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
67
81
  - !ruby/object:Gem::Version
68
- version: '0.10'
82
+ version: '0'
69
83
  description: Adds several methods similar to Enumerable’s iterators to where it is
70
84
  included.
71
85
  email: