source: EcnlProtoTool/trunk/mruby-1.2.0/mrbgems/mruby-enum-ext/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: 17.5 KB
Line 
1##
2# Enumerable
3#
4module Enumerable
5 ##
6 # call-seq:
7 # enum.drop(n) -> array
8 #
9 # Drops first n elements from <i>enum</i>, and returns rest elements
10 # in an array.
11 #
12 # a = [1, 2, 3, 4, 5, 0]
13 # a.drop(3) #=> [4, 5, 0]
14
15 def drop(n)
16 raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int)
17 raise ArgumentError, "attempt to drop negative size" if n < 0
18
19 n = n.to_int
20 ary = []
21 self.each {|*val| n == 0 ? ary << val.__svalue : n -= 1 }
22 ary
23 end
24
25 ##
26 # call-seq:
27 # enum.drop_while {|arr| block } -> array
28 # enum.drop_while -> an_enumerator
29 #
30 # Drops elements up to, but not including, the first element for
31 # which the block returns +nil+ or +false+ and returns an array
32 # containing the remaining elements.
33 #
34 # If no block is given, an enumerator is returned instead.
35 #
36 # a = [1, 2, 3, 4, 5, 0]
37 # a.drop_while {|i| i < 3 } #=> [3, 4, 5, 0]
38
39 def drop_while(&block)
40 return to_enum :drop_while unless block
41
42 ary, state = [], false
43 self.each do |*val|
44 state = true if !state and !block.call(*val)
45 ary << val.__svalue if state
46 end
47 ary
48 end
49
50 ##
51 # call-seq:
52 # enum.take(n) -> array
53 #
54 # Returns first n elements from <i>enum</i>.
55 #
56 # a = [1, 2, 3, 4, 5, 0]
57 # a.take(3) #=> [1, 2, 3]
58
59 def take(n)
60 raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int)
61 raise ArgumentError, "attempt to take negative size" if n < 0
62
63 n = n.to_int
64 ary = []
65 self.each do |*val|
66 break if ary.size >= n
67 ary << val.__svalue
68 end
69 ary
70 end
71
72 ##
73 # call-seq:
74 # enum.take_while {|arr| block } -> array
75 # enum.take_while -> an_enumerator
76 #
77 # Passes elements to the block until the block returns +nil+ or +false+,
78 # then stops iterating and returns an array of all prior elements.
79 #
80 # If no block is given, an enumerator is returned instead.
81 #
82 # a = [1, 2, 3, 4, 5, 0]
83 # a.take_while {|i| i < 3 } #=> [1, 2]
84 #
85 def take_while(&block)
86 return to_enum :take_while unless block
87
88 ary = []
89 self.each do |*val|
90 return ary unless block.call(*val)
91 ary << val.__svalue
92 end
93 ary
94 end
95
96 ##
97 # Iterates the given block for each array of consecutive <n>
98 # elements.
99 #
100 # @return [nil]
101 #
102 # @example
103 # (1..10).each_cons(3) {|a| p a}
104 # # outputs below
105 # [1, 2, 3]
106 # [2, 3, 4]
107 # [3, 4, 5]
108 # [4, 5, 6]
109 # [5, 6, 7]
110 # [6, 7, 8]
111 # [7, 8, 9]
112 # [8, 9, 10]
113
114 def each_cons(n, &block)
115 raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int)
116 raise ArgumentError, "invalid size" if n <= 0
117
118 return to_enum(:each_cons,n) unless block
119 ary = []
120 n = n.to_int
121 self.each do |*val|
122 ary.shift if ary.size == n
123 ary << val.__svalue
124 block.call(ary.dup) if ary.size == n
125 end
126 end
127
128 ##
129 # Iterates the given block for each slice of <n> elements.
130 #
131 # @return [nil]
132 #
133 # @example
134 # (1..10).each_slice(3) {|a| p a}
135 # # outputs below
136 # [1, 2, 3]
137 # [4, 5, 6]
138 # [7, 8, 9]
139 # [10]
140
141 def each_slice(n, &block)
142 raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int)
143 raise ArgumentError, "invalid slice size" if n <= 0
144
145 return to_enum(:each_slice,n) unless block
146 ary = []
147 n = n.to_int
148 self.each do |*val|
149 ary << val.__svalue
150 if ary.size == n
151 block.call(ary)
152 ary = []
153 end
154 end
155 block.call(ary) unless ary.empty?
156 end
157
158 ##
159 # call-seq:
160 # enum.group_by {| obj | block } -> a_hash
161 # enum.group_by -> an_enumerator
162 #
163 # Returns a hash, which keys are evaluated result from the
164 # block, and values are arrays of elements in <i>enum</i>
165 # corresponding to the key.
166 #
167 # (1..6).group_by {|i| i%3} #=> {0=>[3, 6], 1=>[1, 4], 2=>[2, 5]}
168 #
169 def group_by(&block)
170 return to_enum :group_by unless block
171
172 h = {}
173 self.each do |*val|
174 key = block.call(*val)
175 sv = val.__svalue
176 h.key?(key) ? (h[key] << sv) : (h[key] = [sv])
177 end
178 h
179 end
180
181 ##
182 # call-seq:
183 # enum.sort_by { |obj| block } -> array
184 # enum.sort_by -> an_enumerator
185 #
186 # Sorts <i>enum</i> using a set of keys generated by mapping the
187 # values in <i>enum</i> through the given block.
188 #
189 # If no block is given, an enumerator is returned instead.
190
191 def sort_by(&block)
192 return to_enum :sort_by unless block
193
194 ary = []
195 orig = []
196 self.each_with_index{|e, i|
197 orig.push(e)
198 ary.push([block.call(e), i])
199 }
200 if ary.size > 1
201 __sort_sub__(ary, ::Array.new(ary.size), 0, 0, ary.size - 1) do |a,b|
202 a <=> b
203 end
204 end
205 ary.collect{|e,i| orig[i]}
206 end
207
208 NONE = Object.new
209 ##
210 # call-seq:
211 # enum.first -> obj or nil
212 # enum.first(n) -> an_array
213 #
214 # Returns the first element, or the first +n+ elements, of the enumerable.
215 # If the enumerable is empty, the first form returns <code>nil</code>, and the
216 # second form returns an empty array.
217 def first(n=NONE)
218 if n == NONE
219 self.each do |*val|
220 return val.__svalue
221 end
222 return nil
223 else
224 a = []
225 i = 0
226 self.each do |*val|
227 break if n<=i
228 a.push val.__svalue
229 i += 1
230 end
231 a
232 end
233 end
234
235 ##
236 # call-seq:
237 # enum.count -> int
238 # enum.count(item) -> int
239 # enum.count { |obj| block } -> int
240 #
241 # Returns the number of items in +enum+ through enumeration.
242 # If an argument is given, the number of items in +enum+ that
243 # are equal to +item+ are counted. If a block is given, it
244 # counts the number of elements yielding a true value.
245 def count(v=NONE, &block)
246 count = 0
247 if block
248 self.each do |*val|
249 count += 1 if block.call(*val)
250 end
251 else
252 if v == NONE
253 self.each { count += 1 }
254 else
255 self.each do |*val|
256 count += 1 if val.__svalue == v
257 end
258 end
259 end
260 count
261 end
262
263 ##
264 # call-seq:
265 # enum.flat_map { |obj| block } -> array
266 # enum.collect_concat { |obj| block } -> array
267 # enum.flat_map -> an_enumerator
268 # enum.collect_concat -> an_enumerator
269 #
270 # Returns a new array with the concatenated results of running
271 # <em>block</em> once for every element in <i>enum</i>.
272 #
273 # If no block is given, an enumerator is returned instead.
274 #
275 # [1, 2, 3, 4].flat_map { |e| [e, -e] } #=> [1, -1, 2, -2, 3, -3, 4, -4]
276 # [[1, 2], [3, 4]].flat_map { |e| e + [100] } #=> [1, 2, 100, 3, 4, 100]
277 def flat_map(&block)
278 return to_enum :flat_map unless block
279
280 ary = []
281 self.each do |*e|
282 e2 = block.call(*e)
283 if e2.respond_to? :each
284 e2.each {|e3| ary.push(e3) }
285 else
286 ary.push(e2)
287 end
288 end
289 ary
290 end
291 alias collect_concat flat_map
292
293 ##
294 # call-seq:
295 # enum.max_by {|obj| block } -> obj
296 # enum.max_by -> an_enumerator
297 #
298 # Returns the object in <i>enum</i> that gives the maximum
299 # value from the given block.
300 #
301 # If no block is given, an enumerator is returned instead.
302 #
303 # %w[albatross dog horse].max_by {|x| x.length } #=> "albatross"
304
305 def max_by(&block)
306 return to_enum :max_by unless block
307
308 first = true
309 max = nil
310 max_cmp = nil
311
312 self.each do |*val|
313 if first
314 max = val.__svalue
315 max_cmp = block.call(*val)
316 first = false
317 else
318 if (cmp = block.call(*val)) > max_cmp
319 max = val.__svalue
320 max_cmp = cmp
321 end
322 end
323 end
324 max
325 end
326
327 ##
328 # call-seq:
329 # enum.min_by {|obj| block } -> obj
330 # enum.min_by -> an_enumerator
331 #
332 # Returns the object in <i>enum</i> that gives the minimum
333 # value from the given block.
334 #
335 # If no block is given, an enumerator is returned instead.
336 #
337 # %w[albatross dog horse].min_by {|x| x.length } #=> "dog"
338
339 def min_by(&block)
340 return to_enum :min_by unless block
341
342 first = true
343 min = nil
344 min_cmp = nil
345
346 self.each do |*val|
347 if first
348 min = val.__svalue
349 min_cmp = block.call(*val)
350 first = false
351 else
352 if (cmp = block.call(*val)) < min_cmp
353 min = val.__svalue
354 min_cmp = cmp
355 end
356 end
357 end
358 min
359 end
360
361 ##
362 # call-seq:
363 # enum.minmax -> [min, max]
364 # enum.minmax { |a, b| block } -> [min, max]
365 #
366 # Returns two elements array which contains the minimum and the
367 # maximum value in the enumerable. The first form assumes all
368 # objects implement <code>Comparable</code>; the second uses the
369 # block to return <em>a <=> b</em>.
370 #
371 # a = %w(albatross dog horse)
372 # a.minmax #=> ["albatross", "horse"]
373 # a.minmax { |a, b| a.length <=> b.length } #=> ["dog", "albatross"]
374
375 def minmax(&block)
376 max = nil
377 min = nil
378 first = true
379
380 self.each do |*val|
381 if first
382 val = val.__svalue
383 max = val
384 min = val
385 first = false
386 else
387 if block
388 max = val.__svalue if block.call(*val, max) > 0
389 min = val.__svalue if block.call(*val, min) < 0
390 else
391 val = val.__svalue
392 max = val if (val <=> max) > 0
393 min = val if (val <=> min) < 0
394 end
395 end
396 end
397 [min, max]
398 end
399
400 ##
401 # call-seq:
402 # enum.minmax_by { |obj| block } -> [min, max]
403 # enum.minmax_by -> an_enumerator
404 #
405 # Returns a two element array containing the objects in
406 # <i>enum</i> that correspond to the minimum and maximum values respectively
407 # from the given block.
408 #
409 # If no block is given, an enumerator is returned instead.
410 #
411 # %w(albatross dog horse).minmax_by { |x| x.length } #=> ["dog", "albatross"]
412
413 def minmax_by(&block)
414 return to_enum :minmax_by unless block
415
416 max = nil
417 max_cmp = nil
418 min = nil
419 min_cmp = nil
420 first = true
421
422 self.each do |*val|
423 if first
424 max = min = val.__svalue
425 max_cmp = min_cmp = block.call(*val)
426 first = false
427 else
428 if (cmp = block.call(*val)) > max_cmp
429 max = val.__svalue
430 max_cmp = cmp
431 end
432 if (cmp = block.call(*val)) < min_cmp
433 min = val.__svalue
434 min_cmp = cmp
435 end
436 end
437 end
438 [min, max]
439 end
440
441 ##
442 # call-seq:
443 # enum.none? [{ |obj| block }] -> true or false
444 #
445 # Passes each element of the collection to the given block. The method
446 # returns <code>true</code> if the block never returns <code>true</code>
447 # for all elements. If the block is not given, <code>none?</code> will return
448 # <code>true</code> only if none of the collection members is true.
449 #
450 # %w(ant bear cat).none? { |word| word.length == 5 } #=> true
451 # %w(ant bear cat).none? { |word| word.length >= 4 } #=> false
452 # [].none? #=> true
453 # [nil, false].none? #=> true
454 # [nil, true].none? #=> false
455
456 def none?(&block)
457 if block
458 self.each do |*val|
459 return false if block.call(*val)
460 end
461 else
462 self.each do |*val|
463 return false if val.__svalue
464 end
465 end
466 true
467 end
468
469 ##
470 # call-seq:
471 # enum.one? [{ |obj| block }] -> true or false
472 #
473 # Passes each element of the collection to the given block. The method
474 # returns <code>true</code> if the block returns <code>true</code>
475 # exactly once. If the block is not given, <code>one?</code> will return
476 # <code>true</code> only if exactly one of the collection members is
477 # true.
478 #
479 # %w(ant bear cat).one? { |word| word.length == 4 } #=> true
480 # %w(ant bear cat).one? { |word| word.length > 4 } #=> false
481 # %w(ant bear cat).one? { |word| word.length < 4 } #=> false
482 # [nil, true, 99].one? #=> false
483 # [nil, true, false].one? #=> true
484 #
485
486 def one?(&block)
487 count = 0
488 if block
489 self.each do |*val|
490 count += 1 if block.call(*val)
491 return false if count > 1
492 end
493 else
494 self.each do |*val|
495 count += 1 if val.__svalue
496 return false if count > 1
497 end
498 end
499
500 count == 1 ? true : false
501 end
502
503 ##
504 # call-seq:
505 # enum.each_with_object(obj) { |(*args), memo_obj| ... } -> obj
506 # enum.each_with_object(obj) -> an_enumerator
507 #
508 # Iterates the given block for each element with an arbitrary
509 # object given, and returns the initially given object.
510 #
511 # If no block is given, returns an enumerator.
512 #
513 # (1..10).each_with_object([]) { |i, a| a << i*2 }
514 # #=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
515 #
516
517 def each_with_object(obj=nil, &block)
518 raise ArgumentError, "wrong number of arguments (0 for 1)" if obj.nil?
519
520 return to_enum(:each_with_object, obj) unless block
521
522 self.each {|*val| block.call(val.__svalue, obj) }
523 obj
524 end
525
526 ##
527 # call-seq:
528 # enum.reverse_each { |item| block } -> enum
529 # enum.reverse_each -> an_enumerator
530 #
531 # Builds a temporary array and traverses that array in reverse order.
532 #
533 # If no block is given, an enumerator is returned instead.
534 #
535 # (1..3).reverse_each { |v| p v }
536 #
537 # produces:
538 #
539 # 3
540 # 2
541 # 1
542 #
543
544 def reverse_each(&block)
545 return to_enum :reverse_each unless block
546
547 ary = self.to_a
548 i = ary.size - 1
549 while i>=0
550 block.call(ary[i])
551 i -= 1
552 end
553 self
554 end
555
556 ##
557 # call-seq:
558 # enum.cycle(n=nil) { |obj| block } -> nil
559 # enum.cycle(n=nil) -> an_enumerator
560 #
561 # Calls <i>block</i> for each element of <i>enum</i> repeatedly _n_
562 # times or forever if none or +nil+ is given. If a non-positive
563 # number is given or the collection is empty, does nothing. Returns
564 # +nil+ if the loop has finished without getting interrupted.
565 #
566 # Enumerable#cycle saves elements in an internal array so changes
567 # to <i>enum</i> after the first pass have no effect.
568 #
569 # If no block is given, an enumerator is returned instead.
570 #
571 # a = ["a", "b", "c"]
572 # a.cycle { |x| puts x } # print, a, b, c, a, b, c,.. forever.
573 # a.cycle(2) { |x| puts x } # print, a, b, c, a, b, c.
574 #
575
576 def cycle(n=nil, &block)
577 return to_enum(:cycle, n) if !block && n.nil?
578
579 ary = []
580 if n.nil?
581 self.each do|*val|
582 ary.push val
583 block.call(*val)
584 end
585 loop do
586 ary.each do|e|
587 block.call(*e)
588 end
589 end
590 else
591 raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int)
592
593 n = n.to_int
594 self.each do|*val|
595 ary.push val
596 end
597 count = 0
598 while count < n
599 ary.each do|e|
600 block.call(*e)
601 end
602 count += 1
603 end
604 end
605 end
606
607 ##
608 # call-seq:
609 # enum.find_index(value) -> int or nil
610 # enum.find_index { |obj| block } -> int or nil
611 # enum.find_index -> an_enumerator
612 #
613 # Compares each entry in <i>enum</i> with <em>value</em> or passes
614 # to <em>block</em>. Returns the index for the first for which the
615 # evaluated value is non-false. If no object matches, returns
616 # <code>nil</code>
617 #
618 # If neither block nor argument is given, an enumerator is returned instead.
619 #
620 # (1..10).find_index { |i| i % 5 == 0 and i % 7 == 0 } #=> nil
621 # (1..100).find_index { |i| i % 5 == 0 and i % 7 == 0 } #=> 34
622 # (1..100).find_index(50) #=> 49
623 #
624
625 def find_index(val=NONE, &block)
626 return to_enum(:find_index, val) if !block && val == NONE
627
628 idx = 0
629 if block
630 self.each do |*e|
631 return idx if block.call(*e)
632 idx += 1
633 end
634 else
635 self.each do |*e|
636 return idx if e.__svalue == val
637 idx += 1
638 end
639 end
640 nil
641 end
642
643 ##
644 # call-seq:
645 # enum.zip(arg, ...) -> an_array_of_array
646 #
647 # Takes one element from <i>enum</i> and merges corresponding
648 # elements from each <i>args</i>. This generates a sequence of
649 # <em>n</em>-element arrays, where <em>n</em> is one more than the
650 # count of arguments. The length of the resulting sequence will be
651 # <code>enum#size</code>. If the size of any argument is less than
652 # <code>enum#size</code>, <code>nil</code> values are supplied.
653 #
654
655 def zip(*arg)
656 ary = []
657 arg = arg.map{|a|a.to_a}
658 i = 0
659 self.each do |*val|
660 a = []
661 a.push(val.__svalue)
662 idx = 0
663 while idx < arg.size
664 a.push(arg[idx][i])
665 idx += 1
666 end
667 ary.push(a)
668 i += 1
669 end
670 ary
671 end
672
673 ##
674 # call-seq:
675 # enum.to_h -> hash
676 #
677 # Returns the result of interpreting <i>enum</i> as a list of
678 # <tt>[key, value]</tt> pairs.
679 #
680 # %i[hello world].each_with_index.to_h
681 # # => {:hello => 0, :world => 1}
682 #
683
684 def to_h
685 h = {}
686 self.each do |*v|
687 v = v.__svalue
688 raise TypeError, "wrong element type #{v.class} (expected Array)" unless v.is_a? Array
689 raise ArgumentError, "element has wrong array length (expected 2, was #{v.size})" if v.size != 2
690 h[v[0]] = v[1]
691 end
692 h
693 end
694
695 def nil.to_h
696 {}
697 end
698end
Note: See TracBrowser for help on using the repository browser.