diff options
author | mame <mame@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2016-03-17 12:14:21 +0000 |
---|---|---|
committer | mame <mame@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2016-03-17 12:14:21 +0000 |
commit | a38d1619b487a9b22422e6be5fdf96d7bdc4b703 (patch) | |
tree | ff47d04d683438a00f3f406bcd3a4e89d9732072 /array.c | |
parent | 4b5cb8b79ce7d60a15b5edeb22637a8366503bbf (diff) | |
download | ruby-a38d1619b487a9b22422e6be5fdf96d7bdc4b703.tar.gz |
* array.c (rb_ary_max, rb_ary_min): Array#max and Array#min added.
[Feature #12172]
* internal.h (OPTIMIZED_CMP): moved from enum.c so that array.c can
use it.
* test/ruby/test_array.rb (test_max, test_min): tests for Array#max
and Array#min.
* test/ruby/test_enum.rb (test_max, test_min): revised a bit to test
Enumerable#max and #min explicitly.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54150 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'array.c')
-rw-r--r-- | array.c | 93 |
1 files changed, 93 insertions, 0 deletions
@@ -4178,6 +4178,96 @@ rb_ary_or(VALUE ary1, VALUE ary2) return ary3; } +/* + * call-seq: + * ary.max -> obj + * ary.max { |a, b| block } -> obj + * ary.max(n) -> array + * ary.max(n) {|a,b| block } -> array + * + * Returns the object in _ary_ with the maximum value. The + * first form assumes all objects implement <code>Comparable</code>; + * the second uses the block to return <em>a <=> b</em>. + * + * a = %w(albatross dog horse) + * a.max #=> "horse" + * a.max { |a, b| a.length <=> b.length } #=> "albatross" + * + * If the +n+ argument is given, maximum +n+ elements are returned + * as an array. + * + * a = %w[albatross dog horse] + * a.max(2) #=> ["horse", "dog"] + * a.max(2) {|a, b| a.length <=> b.length } #=> ["albatross", "horse"] + */ +static VALUE +rb_ary_max(int argc, VALUE *argv, VALUE ary) +{ + struct cmp_opt_data cmp_opt = { 0, 0 }; + VALUE result = Qundef, v; + VALUE num; + long i; + + rb_scan_args(argc, argv, "01", &num); + + if (!NIL_P(num) || rb_block_given_p()) + return rb_call_super(argc, argv); /* XXX: should redefine? */ + + for (i = 0; i < RARRAY_LEN(ary); i++) { + v = RARRAY_AREF(ary, i); + if (result == Qundef || OPTIMIZED_CMP(v, result, cmp_opt) > 0) { + result = v; + } + } + if (result == Qundef) return Qnil; + return result; +} + +/* + * call-seq: + * ary.min -> obj + * ary.min {| a,b | block } -> obj + * ary.min(n) -> array + * ary.min(n) {| a,b | block } -> array + * + * Returns the object in _ary_ with the minimum value. The + * first form assumes all objects implement <code>Comparable</code>; + * the second uses the block to return <em>a <=> b</em>. + * + * a = %w(albatross dog horse) + * a.min #=> "albatross" + * a.min { |a, b| a.length <=> b.length } #=> "dog" + * + * If the +n+ argument is given, minimum +n+ elements are returned + * as an array. + * + * a = %w[albatross dog horse] + * a.min(2) #=> ["albatross", "dog"] + * a.min(2) {|a, b| a.length <=> b.length } #=> ["dog", "horse"] + */ +static VALUE +rb_ary_min(int argc, VALUE *argv, VALUE ary) +{ + struct cmp_opt_data cmp_opt = { 0, 0 }; + VALUE result = Qundef, v; + VALUE num; + long i; + + rb_scan_args(argc, argv, "01", &num); + + if (!NIL_P(num) || rb_block_given_p()) + return rb_call_super(argc, argv); /* XXX: should redefine? */ + + for (i = 0; i < RARRAY_LEN(ary); i++) { + v = RARRAY_AREF(ary, i); + if (result == Qundef || OPTIMIZED_CMP(v, result, cmp_opt) < 0) { + result = v; + } + } + if (result == Qundef) return Qnil; + return result; +} + static int push_value(st_data_t key, st_data_t val, st_data_t ary) { @@ -5867,6 +5957,9 @@ Init_Array(void) rb_define_method(rb_cArray, "&", rb_ary_and, 1); rb_define_method(rb_cArray, "|", rb_ary_or, 1); + rb_define_method(rb_cArray, "max", rb_ary_max, -1); + rb_define_method(rb_cArray, "min", rb_ary_min, -1); + rb_define_method(rb_cArray, "uniq", rb_ary_uniq, 0); rb_define_method(rb_cArray, "uniq!", rb_ary_uniq_bang, 0); rb_define_method(rb_cArray, "compact", rb_ary_compact, 0); |