flex_array 0.2.0 → 0.3.0

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