source: EcnlProtoTool/trunk/mruby-1.2.0/mrblib/enum.rb@ 270

Last change on this file since 270 was 270, checked in by coas-nagasima, 7 years ago

mruby版ECNLプロトタイピング・ツールを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-ruby
File size: 8.3 KB
Line 
1##
2# Enumerable
3#
4# The <code>Enumerable</code> mixin provides collection classes with
5# several traversal and searching methods, and with the ability to
6# sort. The class must provide a method `each`, which
7# yields successive members of the collection. If
8# {Enumerable#max}, {#min}, or
9# {#sort} is used, the objects in the collection must also
10# implement a meaningful `<=>` operator, as these methods
11# rely on an ordering between members of the collection.
12#
13# @ISO 15.3.2
14module Enumerable
15
16 ##
17 # Call the given block for each element
18 # which is yield by +each+. Return false
19 # if one block value is false. Otherwise
20 # return true. If no block is given and
21 # +self+ is false return false.
22 #
23 # ISO 15.3.2.2.1
24 def all?(&block)
25 if block
26 self.each{|*val| return false unless block.call(*val)}
27 else
28 self.each{|*val| return false unless val.__svalue}
29 end
30 true
31 end
32
33 ##
34 # Call the given block for each element
35 # which is yield by +each+. Return true
36 # if one block value is true. Otherwise
37 # return false. If no block is given and
38 # +self+ is true object return true.
39 #
40 # ISO 15.3.2.2.2
41 def any?(&block)
42 if block
43 self.each{|*val| return true if block.call(*val)}
44 else
45 self.each{|*val| return true if val.__svalue}
46 end
47 false
48 end
49
50 ##
51 # Call the given block for each element
52 # which is yield by +each+. Append all
53 # values of each block together and
54 # return this value.
55 #
56 # ISO 15.3.2.2.3
57 def collect(&block)
58 return to_enum :collect unless block
59
60 ary = []
61 self.each{|*val| ary.push(block.call(*val))}
62 ary
63 end
64
65 ##
66 # Call the given block for each element
67 # which is yield by +each+. Return
68 # +ifnone+ if no block value was true.
69 # Otherwise return the first block value
70 # which had was true.
71 #
72 # ISO 15.3.2.2.4
73 def detect(ifnone=nil, &block)
74 ret = ifnone
75 self.each{|*val|
76 if block.call(*val)
77 ret = val.__svalue
78 break
79 end
80 }
81 ret
82 end
83
84 ##
85 # Call the given block for each element
86 # which is yield by +each+. Pass an
87 # index to the block which starts at 0
88 # and increase by 1 for each element.
89 #
90 # ISO 15.3.2.2.5
91 def each_with_index(&block)
92 return to_enum :each_with_index unless block
93
94 i = 0
95 self.each{|*val|
96 block.call(val.__svalue, i)
97 i += 1
98 }
99 self
100 end
101
102 ##
103 # Return an array of all elements which
104 # are yield by +each+.
105 #
106 # ISO 15.3.2.2.6
107 def entries
108 ary = []
109 self.each{|*val|
110 # __svalue is an internal method
111 ary.push val.__svalue
112 }
113 ary
114 end
115
116 ##
117 # Alias for find
118 #
119 # ISO 15.3.2.2.7
120 alias find detect
121
122 ##
123 # Call the given block for each element
124 # which is yield by +each+. Return an array
125 # which contains all elements whose block
126 # value was true.
127 #
128 # ISO 15.3.2.2.8
129 def find_all(&block)
130 return to_enum :find_all unless block
131
132 ary = []
133 self.each{|*val|
134 ary.push(val.__svalue) if block.call(*val)
135 }
136 ary
137 end
138
139 ##
140 # Call the given block for each element
141 # which is yield by +each+ and which return
142 # value was true when invoking === with
143 # +pattern+. Return an array with all
144 # elements or the respective block values.
145 #
146 # ISO 15.3.2.2.9
147 def grep(pattern, &block)
148 ary = []
149 self.each{|*val|
150 sv = val.__svalue
151 if pattern === sv
152 ary.push((block)? block.call(*val): sv)
153 end
154 }
155 ary
156 end
157
158 ##
159 # Return true if at least one element which
160 # is yield by +each+ returns a true value
161 # by invoking == with +obj+. Otherwise return
162 # false.
163 #
164 # ISO 15.3.2.2.10
165 def include?(obj)
166 self.each{|*val|
167 return true if val.__svalue == obj
168 }
169 false
170 end
171
172 ##
173 # Call the given block for each element
174 # which is yield by +each+. Return value
175 # is the sum of all block values. Pass
176 # to each block the current sum and the
177 # current element.
178 #
179 # ISO 15.3.2.2.11
180 def inject(*args, &block)
181 raise ArgumentError, "too many arguments" if args.size > 2
182 if Symbol === args[-1]
183 sym = args[-1]
184 block = ->(x,y){x.__send__(sym,y)}
185 args.pop
186 end
187 if args.empty?
188 flag = true # no initial argument
189 result = nil
190 else
191 flag = false
192 result = args[0]
193 end
194 self.each{|*val|
195 val = val.__svalue
196 if flag
197 # push first element as initial
198 flag = false
199 result = val
200 else
201 result = block.call(result, val)
202 end
203 }
204 result
205 end
206 alias reduce inject
207
208 ##
209 # Alias for collect
210 #
211 # ISO 15.3.2.2.12
212 alias map collect
213
214 ##
215 # Return the maximum value of all elements
216 # yield by +each+. If no block is given <=>
217 # will be invoked to define this value. If
218 # a block is given it will be used instead.
219 #
220 # ISO 15.3.2.2.13
221 def max(&block)
222 flag = true # 1st element?
223 result = nil
224 self.each{|*val|
225 val = val.__svalue
226 if flag
227 # 1st element
228 result = val
229 flag = false
230 else
231 if block
232 result = val if block.call(val, result) > 0
233 else
234 result = val if (val <=> result) > 0
235 end
236 end
237 }
238 result
239 end
240
241 ##
242 # Return the minimum value of all elements
243 # yield by +each+. If no block is given <=>
244 # will be invoked to define this value. If
245 # a block is given it will be used instead.
246 #
247 # ISO 15.3.2.2.14
248 def min(&block)
249 flag = true # 1st element?
250 result = nil
251 self.each{|*val|
252 val = val.__svalue
253 if flag
254 # 1st element
255 result = val
256 flag = false
257 else
258 if block
259 result = val if block.call(val, result) < 0
260 else
261 result = val if (val <=> result) < 0
262 end
263 end
264 }
265 result
266 end
267
268 ##
269 # Alias for include?
270 #
271 # ISO 15.3.2.2.15
272 alias member? include?
273
274 ##
275 # Call the given block for each element
276 # which is yield by +each+. Return an
277 # array which contains two arrays. The
278 # first array contains all elements
279 # whose block value was true. The second
280 # array contains all elements whose
281 # block value was false.
282 #
283 # ISO 15.3.2.2.16
284 def partition(&block)
285 ary_T = []
286 ary_F = []
287 self.each{|*val|
288 if block.call(*val)
289 ary_T.push(val.__svalue)
290 else
291 ary_F.push(val.__svalue)
292 end
293 }
294 [ary_T, ary_F]
295 end
296
297 ##
298 # Call the given block for each element
299 # which is yield by +each+. Return an
300 # array which contains only the elements
301 # whose block value was false.
302 #
303 # ISO 15.3.2.2.17
304 def reject(&block)
305 ary = []
306 self.each{|*val|
307 ary.push(val.__svalue) unless block.call(*val)
308 }
309 ary
310 end
311
312 ##
313 # Alias for find_all.
314 #
315 # ISO 15.3.2.2.18
316 alias select find_all
317
318 ##
319 # TODO
320 # Does this OK? Please test it.
321 def __sort_sub__(sorted, work, src_ary, head, tail, &block)
322 if head == tail
323 sorted[head] = work[head] if src_ary == 1
324 return
325 end
326
327 # on current step, which is a src ary?
328 if src_ary == 0
329 src, dst = sorted, work
330 else
331 src, dst = work, sorted
332 end
333
334 key = src[head] # key value for dividing values
335 i, j = head, tail # position to store on the dst ary
336
337 (head + 1).upto(tail){|idx|
338 if ((block)? block.call(src[idx], key): (src[idx] <=> key)) > 0
339 # larger than key
340 dst[j] = src[idx]
341 j -= 1
342 else
343 dst[i] = src[idx]
344 i += 1
345 end
346 }
347
348 sorted[i] = key
349
350 # sort each sub-array
351 src_ary = (src_ary + 1) % 2 # exchange a src ary
352 __sort_sub__(sorted, work, src_ary, head, i - 1, &block) if i > head
353 __sort_sub__(sorted, work, src_ary, i + 1, tail, &block) if i < tail
354 end
355# private :__sort_sub__
356
357 ##
358 # Return a sorted array of all elements
359 # which are yield by +each+. If no block
360 # is given <=> will be invoked on each
361 # element to define the order. Otherwise
362 # the given block will be used for
363 # sorting.
364 #
365 # ISO 15.3.2.2.19
366 def sort(&block)
367 ary = []
368 self.each{|*val| ary.push(val.__svalue)}
369 if ary.size > 1
370 __sort_sub__(ary, ::Array.new(ary.size), 0, 0, ary.size - 1, &block)
371 end
372 ary
373 end
374
375 ##
376 # Alias for entries.
377 #
378 # ISO 15.3.2.2.20
379 alias to_a entries
380
381 # redefine #hash 15.3.1.3.15
382 def hash
383 h = 12347
384 i = 0
385 self.each do |e|
386 n = e.hash << (i % 16)
387 h ^= n
388 i += 1
389 end
390 h
391 end
392end
Note: See TracBrowser for help on using the repository browser.