source: EcnlProtoTool/trunk/mruby-1.3.0/mrbgems/mruby-enum-ext/mrblib/enum.rb@ 331

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

prototoolに関連するプロジェクトをnewlibからmuslを使うよう変更・更新
ntshellをnewlibの下位の実装から、muslのsyscallの実装に変更・更新
以下のOSSをアップデート
・mruby-1.3.0
・musl-1.1.18
・onigmo-6.1.3
・tcc-0.9.27
以下のOSSを追加
・openssl-1.1.0e
・curl-7.57.0
・zlib-1.2.11
以下のmrbgemsを追加
・iij/mruby-digest
・iij/mruby-env
・iij/mruby-errno
・iij/mruby-iijson
・iij/mruby-ipaddr
・iij/mruby-mock
・iij/mruby-require
・iij/mruby-tls-openssl

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