iteraptor 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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: