flex_array 0.2.0 → 0.3.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,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- YzZiYThmNDY2YTU2NGE5YmQzNjUxNjRhODdkMzJiMGEwMWNiM2MwZg==
4
+ OWZiZTdkNTc4MmMyOTBiY2YwMjQ2ZTE5YmU1NWU0YWNmNzQ3MTRiNg==
5
5
  data.tar.gz: !binary |-
6
- M2NjZmZmMjM2ZmEzMGNkNzc1NjFiNWEwNDE4ZTc3Y2M3ZmVkZjYzOQ==
6
+ NjhmZmMxZjFlM2Q1YWM2MDc4YjRhMTVjM2FhOTRmYWE2NTE4MzU1NA==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- MmJlZDVkZTRiMzJhMmU3ZTEyNmU3MmQyM2Q0NWQ3MDAxNTRjZDkzMGRlZjE4
10
- ZjMyY2EzYzA4N2RjY2U5YzVlNjg3NGM4ZTQwNTAxOGFlNWYzYzAyN2MyNjE1
11
- M2FlMWI1N2YwYTk0MGQ4ZTBjMmQ3N2M1MDZjMzYzNjM1YmRmZWY=
9
+ Y2FjMDgyYTRjZGY5NzQ2MzY5MzdjNTJhNGVjZDkyZjRiYTc3ZjBmZWMyMWVj
10
+ MGE1ZmU5NTBjMzQ0Y2ViOGEyYTc5ZGFmMGQyZGE4YzljYzMzNGU4NWQ4MTRm
11
+ NjQzOWEzNGMwZGM3OTE0YjFkZWE1ODljMTY1YzE2MzEwZTkyOWU=
12
12
  data.tar.gz: !binary |-
13
- MjYwNDJkODI2YzA2YTE0NTY5MmZiZmQxNGYyNzA0NzExYzI0YWI1N2U3MGVm
14
- NDliYWIxZTQyYjJhYzQzM2I4NDljOTI0NGZlZDQwNjlhMThmYjU2NDA5OGJk
15
- NjQxZGM3YWEzZWIyYmU0MzA4NzNjYjgyYjNlNjkwMTdmZDgwMjg=
13
+ ZTNmMDUwOGEyNGRmYzljZjhjMjhlOWQ1NjVjMjlmNDA4MjZhODAyM2I2OWIy
14
+ NmU4ZWU4M2Y2OWEyOTlkZjgxZmIxZTczM2YxZWNkZDI2YzY4ZTVjMzNlMGMy
15
+ ODU1NGU2NWY5YTZhOTQzNjAyNWJjZGJjNGRiMjU3ZjQ2YmI4MzM=
data/lib/flex_array.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  require 'in_array'
2
+ require_relative 'flex_array/flex_array_forever'
2
3
  require_relative 'flex_array/spec_component'
4
+ require_relative 'flex_array/spec_array'
3
5
  require_relative 'flex_array/object'
4
6
  require_relative 'flex_array/integer'
5
7
  require_relative 'flex_array/range'
@@ -17,14 +19,13 @@ require_relative 'flex_array/flex_array_process'
17
19
  #\FlexArray - A flexible array class.
18
20
  #* flex_array.rb - The root file that gathers up all the flex array parts.
19
21
  class FlexArray
20
- include Enumerable
21
22
  include InArrayAlready
22
23
 
23
24
  #The version of this class.
24
25
  #<br>Returns
25
26
  #* A version string; <major>.<minor>.<step>
26
27
  def self.version
27
- '0.2.0'
28
+ '0.3.0'
28
29
  end
29
30
 
30
31
  #The version of the class of this instance.
@@ -41,16 +42,23 @@ class FlexArray
41
42
  attr_accessor :array_data
42
43
 
43
44
  #The total number of elements in this array.
44
- attr_reader :count
45
+ def length
46
+ @array_specs.spec_count
47
+ end
48
+
49
+ alias size length
45
50
 
46
51
  #The number of dimensions in this array.
47
- attr_reader :dimensions
52
+ def dimensions
53
+ @array_specs.spec_dimensions
54
+ end
55
+
56
+ #Is this flex array transposed?
57
+ attr_reader :transposed
48
58
 
49
59
  #Get the limits of the subscripts of the flex array.
50
- #<br>Returns
51
- #* An array of dimension limits ranges.
52
60
  def limits
53
- Array.new(@dimensions) {|dimension| @array_specs[dimension].range}
61
+ @array_specs.collect {|spec| spec.range }
54
62
  end
55
63
 
56
64
  #Return this flex array as a flex array!
@@ -79,11 +87,9 @@ class FlexArray
79
87
  def <=>(other)
80
88
  @array_data <=> other.array_data
81
89
  end
82
-
83
- #Update the count and dimensions variables
84
- def update_count_and_dimensions
85
- @dimensions = @array_specs.length
86
- @count = @array_data.length
87
- self
90
+
91
+ #Is this flex array empty?
92
+ def empty?
93
+ length == 0
88
94
  end
89
95
  end
@@ -1,5 +1,3 @@
1
- require_relative '../flex_array'
2
-
3
1
  #Extensions to Array needed to support flex array.
4
2
  class Array
5
3
  #Get the specifications of the array index values.
@@ -8,23 +6,21 @@ class Array
8
6
  def limits
9
7
  [0...self.length]
10
8
  end
11
-
9
+
12
10
  #Quick access to the limits for internal use.
13
11
  #<br>Returns
14
12
  #* An array with one spec component in it.
15
13
  def array_specs
16
- [SpecComponent.new(0...self.length, 1)]
14
+ SpecArray.new([0...self.length])
17
15
  end
18
-
16
+
19
17
  #Quick access to the array data for internal use.
20
18
  #<br>Returns
21
19
  #* An array -- self
22
20
  def array_data
23
21
  self
24
22
  end
25
-
26
- alias :length :count
27
-
23
+
28
24
  #Convert this array to an range index against the spec.
29
25
  #<br>Parameters
30
26
  #* spec - The spec component used to validate this index.
@@ -33,22 +29,26 @@ class Array
33
29
  #<br>Exceptions
34
30
  #* IndexError if the range is not valid.
35
31
  def to_index_range(spec)
36
- self_min, self_max, spec_max = Integer(self[0]), Integer(self[1]), spec.max
37
- self_min = spec_max + self_min + 1 if self_min < 0
38
- self_max = spec_max + self_max + 1 if self_max < 0
39
-
40
- if self.length == 2 && self_min <= self_max && spec === self_min && spec === self_max
41
- self_min..self_max
42
- else
43
- fail IndexError, "Subscript invalid or out of range: #{self.inspect}"
32
+ spec_max = spec.max
33
+
34
+ self.collect do |value|
35
+ value = Integer(value)
36
+ value = spec_max + value + 1 if value < 0
37
+
38
+ unless spec === value
39
+ fail IndexError, "Subscript invalid or out of range: #{self.inspect}"
40
+ end
41
+
42
+ value
44
43
  end
45
- end
46
-
44
+ end
45
+
47
46
  #Return this flex array as a flex array!
48
47
  #<br>Returns
49
48
  #* A flex array that references this array.
50
49
  #<br>Note
51
- #* To avoid a shared reference, use my_array.dup.to_flex_array instead.
50
+ #* To avoid a shared reference, use my_array.dup.to_flex_array or
51
+ # FlexArray.new_from_array(my_array.dup) instead.
52
52
  def to_flex_array
53
53
  FlexArray.new_from_array(self)
54
54
  end
@@ -8,10 +8,10 @@ class FlexArray
8
8
  #<br>Exceptions
9
9
  #* ArgumentError if the data may not be appended.
10
10
  def << (data)
11
+ fail "Cannot append to a transposed array." if @transposed
11
12
  specs = get_append_specs(data = data.in_array)
12
- data.array_data.each {|element| @array_data << element }
13
- @array_specs[0].enlarge(specs[0].span)
14
- @count += data.count
13
+ @array_data += data.array_data
14
+ @array_specs.enlarge(specs[0].span)
15
15
  self
16
16
  end
17
17
 
@@ -33,19 +33,19 @@ class FlexArray
33
33
  #* ArgumentError if the data may not be appended.
34
34
  def get_append_specs(data)
35
35
  spec_len = (specs = data.array_specs).length
36
-
37
- if @dimensions == spec_len+1
38
- specs.insert(0, SpecComponent.new(0...1, nil))
39
- elsif @dimensions != spec_len
36
+
37
+ if dimensions == spec_len+1
38
+ specs = specs.dup.insert(0, SpecComponent.new(0...1, nil))
39
+ elsif dimensions != spec_len
40
40
  fail ArgumentError, "Incompatible dimensionality error on <<."
41
41
  end
42
-
43
- (1...@dimensions).each do |index|
44
- unless @array_specs[index] == specs[index]
42
+
43
+ (1...dimensions).each do |index|
44
+ unless @array_specs[index].span == specs[index].span
45
45
  fail ArgumentError, "Dimension mismatch error on <<."
46
46
  end
47
47
  end
48
-
48
+
49
49
  specs
50
50
  end
51
51
  end
@@ -1,98 +1,435 @@
1
1
  #* flex_array_each.rb - The flexible array class each and related methods.
2
+ # :reek:RepeatedConditional - @transposed determines if short cuts are allowed.
2
3
  class FlexArray
3
- #Process the standard :each operator.
4
+ include Enumerable
5
+
6
+ #Retrieve data from the array endlessly repeating as needed.
4
7
  #<br>Parameters
5
- #* indexes - An array with as many entries as the flexible array has
6
- # dimensions. See [] for more details. Note that since indexes is NOT
7
- # a splat parameter, it must be passed as an array explicitly. If omitted
8
- # or passed in as [:all] all elements of the array are processed.
8
+ #* count - The number of times to cycle through the flex array. Defaults to
9
+ # cycling forever.
9
10
  #* block - The optional block to be executed for each selected array element.
10
- # The return value is the last value returned by the block. If the block
11
- # is not present, an enumerator object is returned.
11
+ # The return value is the last value returned by the block. If the block
12
+ # is not present, then an enumerator object is returned.
13
+ #<br>Returns
14
+ #* nil or an enumerator if no block is provided.
12
15
  #<br>Block Arguments
13
16
  #* value - Each value selected by the iteration.
14
- def each(indexes=[:all], &block)
15
- if validate_all_or_index_count(indexes)
16
- @array_data.each(&block)
17
- elsif block_given?
18
- process_indexes(indexes) {|_index, posn| block.call(@array_data[posn])}
19
- else
20
- Enumerator.new do |yielder|
21
- process_indexes(indexes) {|_index, posn| yielder.yield(@array_data[posn])}
17
+ #<br>Endemic Code Smells
18
+ #* :reek:NestedIterators
19
+ def cycle(count = FOREVER, &block)
20
+ if block_given?
21
+ if @transposed && length > 0
22
+ count.times do
23
+ process_all do |_index, posn|
24
+ block.call(@array_data[posn])
25
+ end
26
+ end
27
+
28
+ nil
29
+ else
30
+ @array_data.cycle(count.to_i, &block)
22
31
  end
32
+ else
33
+ self.to_enum(:cycle, count)
23
34
  end
24
35
  end
25
36
 
26
- #Retrieve data from the array endlessly repeating as needed.
37
+ #Retrieve data from a subset of the flex array endlessly repeating as needed.
27
38
  #<br>Parameters
28
- #* indexes - An array with as many entries as the flexible array has
39
+ #* indexes - An array with as many entries as the flexible array has
29
40
  # dimensions. See [] for more details. Note that since indexes is NOT
30
- # a splat parameter, it must be passed as an array explicitly. If omitted
31
- # or passed in as [:all] all elements of the array are processed.
41
+ # a splat parameter, it must be passed as an array explicitly.
42
+ #* count - The number of times to cycle through the flex array. Defaults to
43
+ # cycling forever.
32
44
  #* block - The optional block to be executed for each selected array element.
33
- # The return value is the last value returned by the block. If the block
45
+ # The return value is the last value returned by the block. If the block
34
46
  # is not present, then an enumerator object is returned.
47
+ #<br>Returns
48
+ #* nil or an enumerator if no block is provided.
35
49
  #<br>Block Arguments
36
- #* value - Each value selected by the iteration.
37
- def cycle(indexes=[:all], &block)
38
- if validate_all_or_index_count(indexes)
39
- @array_data.cycle(&block)
40
- elsif block_given?
41
- loop {process_indexes(indexes) {|_index, posn| block.call(@array_data[posn])}}
50
+ #* value - Each value selected by the iteration.
51
+ #<br>Endemic Code Smells
52
+ #* :reek:NestedIterators
53
+ def select_cycle(indexes, count = FOREVER, &block)
54
+ validate_index_count(indexes)
55
+
56
+ if block_given?
57
+ unless empty?
58
+ count.times do
59
+ process_indexes(indexes) do |_index, posn|
60
+ block.call(@array_data[posn])
61
+ end
62
+ end
63
+ end
64
+
65
+ nil
42
66
  else
43
- Enumerator.new do |yielder|
44
- loop {process_indexes(indexes) {|_index, posn| yielder.yield(@array_data[posn])}}
67
+ self.to_enum(:select_cycle, indexes, count)
68
+ end
69
+ end
70
+
71
+ #Process the standard each operator.
72
+ #<br>Parameters
73
+ #* block - The optional block to be executed for each selected array element.
74
+ #<br>Returns
75
+ #* If the block is not present, then an enumerator object is returned.
76
+ # Otherwise the flex array is returned.
77
+ #<br>Block Arguments
78
+ #* value - Each value selected by the iteration.
79
+ def each(&block)
80
+ if block_given?
81
+ if @transposed
82
+ process_all {|_index, posn| block.call(@array_data[posn])}
83
+ else
84
+ @array_data.each(&block)
45
85
  end
86
+
87
+ self
88
+ else
89
+ self.to_enum(:each)
46
90
  end
47
91
  end
48
-
49
- #Process the standard :each_with_index operator.
92
+
93
+ #Process the enhanced select_each operator.
50
94
  #<br>Parameters
51
- #* indexes - An array with as many entries as the flexible array has
95
+ #* indexes - An array with as many entries as the flexible array has
52
96
  # dimensions. See [] for more details. Note that since indexes is NOT
53
- # a splat parameter, it must be passed as an array explicitly. If omitted
54
- # or passed in as [:all] all elements of the array are processed.
97
+ # a splat parameter, it must be passed as an array explicitly
55
98
  #* block - The optional block to be executed for each selected array element.
56
- # The return value is the last value returned by the block. If the block
57
- # is not present, then an enumerator object is returned.
99
+ #<br>Returns
100
+ #* If the block is not present, then an enumerator object is returned.
101
+ # Otherwise the flex array is returned.
102
+ #<br>Block Arguments
103
+ #* value - Each value selected by the iteration.
104
+ def select_each(indexes, &block)
105
+ validate_index_count(indexes)
106
+
107
+ if block_given?
108
+ process_indexes(indexes) {|_index, posn| block.call(@array_data[posn])}
109
+ self
110
+ else
111
+ self.to_enum(:select_each, indexes)
112
+ end
113
+ end
114
+
115
+ #Process the standard each_with_index operator.
116
+ #<br>Parameters
117
+ #* block - The optional block to be executed for each selected array element.
118
+ #<br>Returns
119
+ #* If the block is not present, then an enumerator object is returned.
120
+ # Otherwise the flex array is returned.
58
121
  #<br>Block Arguments
59
122
  #* value - Each value selected by the iteration.
60
123
  #* index - An array with the full index of the selected value.
61
- def each_with_index(indexes=[:all], &block)
62
- validate_all_or_index_count(indexes)
124
+ def each_with_index(&block)
125
+ if block_given?
126
+ process_all {|index, posn| block.call(@array_data[posn], index)}
127
+ self
128
+ else
129
+ self.to_enum(:each_with_index)
130
+ end
131
+ end
132
+
133
+ #Process the enhanced select_each_with_index operator.
134
+ #<br>Parameters
135
+ #* indexes - An array with as many entries as the flexible array has
136
+ # dimensions. See [] for more details. Note that since indexes is NOT
137
+ # a splat parameter, it must be passed as an array explicitly.
138
+ #* block - The optional block to be executed for each selected array element.
139
+ #<br>Returns
140
+ #* If the block is not present, then an enumerator object is returned.
141
+ # Otherwise the flex array is returned.
142
+ #<br>Block Arguments
143
+ #* value - Each value selected by the iteration.
144
+ #* index - An array with the full index of the selected value.
145
+ def select_each_with_index(indexes, &block)
146
+ validate_index_count(indexes)
63
147
 
64
148
  if block_given?
65
149
  process_indexes(indexes) {|index, posn| block.call(@array_data[posn], index)}
150
+ self
66
151
  else
67
- Enumerator.new do |yielder|
68
- process_indexes(indexes) {|index, posn| yielder.yield(@array_data[posn], index)}
69
- end
152
+ self.to_enum(:select_each_with_index, indexes)
70
153
  end
71
154
  end
72
-
73
- #A specialized each variant that passes the low level data, the index
155
+
156
+ #A specialized each variant that passes the low level data, the index
74
157
  #and the position to the block.
75
158
  #<br>Parameters
76
- #* indexes - An array with as many entries as the flexible array has
159
+ #* block - The optional block to be executed for each selected array element.
160
+ # The return value is the last value returned by the block. If the block
161
+ # is not present, then an enumerator object is returned.
162
+ #<br>Returns
163
+ #* If the block is not present, then an enumerator object is returned.
164
+ # Otherwise the flex array is returned.
165
+ #<br>Block Arguments
166
+ #* index - An array with the full index of the selected value.
167
+ #* posn - The position of the data in the low level data store.
168
+ def _each_raw(&block)
169
+ if block_given?
170
+ process_all {|index, posn| block.call(index, posn)}
171
+ self
172
+ else
173
+ self.to_enum(:_each_raw)
174
+ end
175
+ end
176
+
177
+ #An enhanced specialized each variant that passes the low level data,
178
+ #the index and the position to the block.
179
+ #<br>Parameters
180
+ #* indexes - An array with as many entries as the flexible array has
77
181
  # dimensions. See [] for more details. Note that since indexes is NOT
78
- # a splat parameter, it must be passed as an array explicitly. If omitted
79
- # or passed in as [:all] all elements of the array are processed.
182
+ # a splat parameter, it must be passed as an array explicitly.
80
183
  #* block - The optional block to be executed for each selected array element.
81
- # The return value is the last value returned by the block. If the block
184
+ # The return value is the last value returned by the block. If the block
82
185
  # is not present, then an enumerator object is returned.
186
+ #<br>Returns
187
+ #* If the block is not present, then an enumerator object is returned.
188
+ # Otherwise the flex array is returned.
83
189
  #<br>Block Arguments
84
- #* data - A reference to the low level data store.
85
190
  #* index - An array with the full index of the selected value.
86
191
  #* posn - The position of the data in the low level data store.
87
- def _each_raw(indexes=[:all], &block)
88
- validate_all_or_index_count(indexes)
192
+ def _select_each_raw(indexes, &block)
193
+ validate_index_count(indexes)
194
+
195
+ if block_given?
196
+ process_indexes(indexes) {|index, posn| block.call(index, posn)}
197
+ self
198
+ else
199
+ self.to_enum(:_select_each_raw, indexes)
200
+ end
201
+ end
202
+
203
+ alias_method :flatten_collect, :collect
204
+
205
+ #The flex array version of collect that returns a flex array.
206
+ #<br>Parameters
207
+ #* block - The optional block to be executed for each selected array element.
208
+ #<br>Returns
209
+ #* An array of the computed objects retuned by the block.
210
+ #<br>Block Arguments
211
+ #* value - Each value selected by the iteration.
212
+ def collect(&block)
213
+ result = self.dup
214
+ result.collect!(&block)
215
+ end
216
+
217
+ #The flex array version of collect that accepts an optional set of indexes
218
+ #to select the data being collected into a flex array.
219
+ #<br>Parameters
220
+ #* indexes - An array with as many entries as the flexible array has
221
+ # dimensions. See [] for more details. Note that since indexes is NOT
222
+ # a splat parameter, it must be passed as an array explicitly.
223
+ #* block - The optional block to be executed for each selected array element.
224
+ #<br>Returns
225
+ #* An array of the computed objects retuned by the block.
226
+ # If the block is not present, an enumerator object is returned.
227
+ #<br>Block Arguments
228
+ #* value - Each value selected by the iteration.
229
+ def select_collect(indexes, &block)
230
+ result = self.dup
231
+ result.select_collect!(indexes, &block)
232
+ end
233
+
234
+ #The flex array version of collect that accepts an optional set of indexes
235
+ #to select the data being collected into a standard array.
236
+ #<br>Parameters
237
+ #* indexes - An array with as many entries as the flexible array has
238
+ # dimensions. See [] for more details. Note that since indexes is NOT
239
+ # a splat parameter, it must be passed as an array explicitly.
240
+ #* block - The optional block to be executed for each selected array element.
241
+ #<br>Returns
242
+ #* An array of the computed objects retuned by the block.
243
+ # If the block is not present, an enumerator object is returned.
244
+ #<br>Block Arguments
245
+ #* value - Each value selected by the iteration.
246
+ def select_flatten_collect(indexes, &block)
247
+ validate_index_count(indexes)
89
248
 
90
249
  if block_given?
91
- process_indexes(indexes) {|index, posn| block.call(@array_data, index, posn)}
250
+ result = []
251
+ process_indexes(indexes) {|_index, posn| result << block.call(@array_data[posn])}
252
+ result
253
+ else
254
+ self.to_enum(:select_collect, indexes)
255
+ end
256
+ end
257
+
258
+ #The flex array version of collect!
259
+ #<br>Parameters
260
+ #* block - The *required* block to be executed for each selected array element.
261
+ # The return value is the last value returned by the block. If the block
262
+ # is not present, an enumerator object is returned.
263
+ #<br>Returns
264
+ #* self
265
+ #<br>Block Arguments
266
+ #* value - Each value selected by the iteration.
267
+ def collect!(&block)
268
+ fail ArgumentError, "A block is required." unless block_given?
269
+
270
+ if @transposed
271
+ process_all {|_index, posn| @array_data[posn] =
272
+ block.call(@array_data[posn])}
92
273
  else
93
- Enumerator.new do |yielder|
94
- process_indexes(indexes) {|index, posn| yielder.yield(@array_data, index, posn)}
274
+ @array_data = @array_data.collect(&block)
275
+ end
276
+
277
+ self
278
+ end
279
+
280
+ #The enhanced flex array version of collect! that accepts a set of indexes
281
+ #to select the data being collected.
282
+ #<br>Parameters
283
+ #* indexes - An array with as many entries as the flexible array has
284
+ # dimensions. See [] for more details. Note that since indexes is NOT
285
+ # a splat parameter, it must be passed as an array explicitly.
286
+ #* block - The *required* block to be executed for each selected array element.
287
+ # The return value is the last value returned by the block. If the block
288
+ # is not present, an enumerator object is returned.
289
+ #<br>Returns
290
+ #* self
291
+ #<br>Block Arguments
292
+ #* value - Each value selected by the iteration.
293
+ def select_collect!(indexes, &block)
294
+ fail ArgumentError, "A block is required." unless block_given?
295
+ validate_index_count(indexes)
296
+
297
+ process_indexes(indexes) {|_index, posn| @array_data[posn] =
298
+ block.call(@array_data[posn])}
299
+
300
+ self
301
+ end
302
+
303
+ #The flex array version of find_index. This returns the
304
+ #coordinates of the first object that matches the search object or is
305
+ #flagged true by the search block.
306
+ #<br>Parameters
307
+ #* object - The optional value to search for.
308
+ #* block - The optional block to be executed for each selected array element.
309
+ # If the block or object are not present, an enumerator object is returned.
310
+ #<br>Returns
311
+ #* The index of the first place that matched or nil if none matched.
312
+ #<br>Block Arguments
313
+ #* value - Each value selected by the iteration.
314
+ def find_index(value = nil, &block)
315
+ blk = get_find_block(value, &block)
316
+
317
+ if blk
318
+ process_all do |index, posn|
319
+ if blk.call(@array_data[posn])
320
+ return index
321
+ end
95
322
  end
323
+
324
+ nil
325
+ else
326
+ self.to_enum(:find_index)
327
+ end
328
+ end
329
+
330
+ #The enhanced flex array version of find_index. This returns the
331
+ #coordinates of the first object that matches the search object or is
332
+ #flagged true by the search block.
333
+ #<br>Parameters
334
+ #* indexes - An array with as many entries as the flexible array has
335
+ # dimensions. See [] for more details. Note that since indexes is NOT
336
+ # a splat parameter, it must be passed as an array explicitly.
337
+ #* object - The optional value to search for.
338
+ #* block - The optional block to be executed for each selected array element.
339
+ # If the block or object are not present, an enumerator object is returned.
340
+ #<br>Returns
341
+ #* The index of the first place that matched or nil if none matched.
342
+ #<br>Block Arguments
343
+ #* value - Each value selected by the iteration.
344
+ def select_find_index(indexes, value = nil, &block)
345
+ validate_index_count(indexes)
346
+ blk = get_find_block(value, &block)
347
+
348
+ if blk
349
+ process_indexes(indexes) do |index, posn|
350
+ if blk.call(@array_data[posn])
351
+ return index
352
+ end
353
+ end
354
+
355
+ nil
356
+ else
357
+ self.to_enum(:select_find_index, indexes)
358
+ end
359
+ end
360
+
361
+ #The improved flex array version of find_index. This returns the
362
+ #coordinates of objects that match the search object or are
363
+ #flagged true by the search block.
364
+ #<br>Parameters
365
+ #* object - The optional value to search for.
366
+ #* block - The optional block to be executed for each selected array element.
367
+ # If the block or object are not present, an enumerator object is returned.
368
+ #<br>Returns
369
+ #* An array of the indexes of the places that matched.
370
+ #<br>Block Arguments
371
+ #* value - Each value selected by the iteration.
372
+ def find_indexes(value = nil, &block)
373
+ blk, result = get_find_block(value, &block), []
374
+
375
+ if blk
376
+ process_all do |index, posn|
377
+ if blk.call(@array_data[posn])
378
+ result << index.dup
379
+ end
380
+ end
381
+
382
+ result
383
+ else
384
+ self.to_enum(:find_indexes)
385
+ end
386
+ end
387
+
388
+ #The enhanced and improved flex array version of find_index. This returns the
389
+ #coordinates of objects that match the search object or are
390
+ #flagged true by the search block.
391
+ #<br>Parameters
392
+ #* indexes - An array with as many entries as the flexible array has
393
+ # dimensions. See [] for more details. Note that since indexes is NOT
394
+ # a splat parameter, it must be passed as an array explicitly.
395
+ #* object - The optional value to search for.
396
+ #* block - The optional block to be executed for each selected array element.
397
+ # If the block or object are not present, an enumerator object is returned.
398
+ #<br>Returns
399
+ #* An array of the indexes of the places that matched.
400
+ #<br>Block Arguments
401
+ #* value - Each value selected by the iteration.
402
+ def select_find_indexes(indexes, value = nil, &block)
403
+ validate_index_count(indexes)
404
+ blk, result = get_find_block(value, &block), []
405
+
406
+ if blk
407
+ process_indexes(indexes) do |index, posn|
408
+ if blk.call(@array_data[posn])
409
+ result << index.dup
410
+ end
411
+ end
412
+
413
+ result
414
+ else
415
+ self.to_enum(:select_find_index, indexes)
416
+ end
417
+ end
418
+
419
+ private
420
+
421
+ #A helper method to determine which block to use in the find_index family.
422
+ #<br>Returns
423
+ #* The block to use or nil.
424
+ #<br>Endemic Code Smells
425
+ #* :reek:NilCheck
426
+ def get_find_block(value, &block)
427
+ if block_given?
428
+ block
429
+ elsif value.nil?
430
+ nil
431
+ else
432
+ lambda {|obj| obj == value }
96
433
  end
97
434
  end
98
- end
435
+ end