diff options
author | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2004-07-14 14:51:42 +0000 |
---|---|---|
committer | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2004-07-14 14:51:42 +0000 |
commit | 6c6a24826c5fda68e04e71ac17620b0e70bca265 (patch) | |
tree | c2692457fbae375c8a38fd64a90a852365e331fc /enum.c | |
parent | 1a760a6f76e5b2fad343fce10ebf831fe22286b4 (diff) | |
download | ruby-6c6a24826c5fda68e04e71ac17620b0e70bca265.tar.gz |
* enum.c (enum_min_by): new method Enum#min_by. added Enum#max_by
as well.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@6629 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'enum.c')
-rw-r--r-- | enum.c | 102 |
1 files changed, 88 insertions, 14 deletions
@@ -677,20 +677,6 @@ enum_min(obj) return result; } -/* - * call-seq: - * enum.max => obj - * enum.max {| a,b | block } => obj - * - * Returns the object in <i>enum</i> 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" - */ - static VALUE max_i(i, memo) VALUE i; @@ -757,6 +743,92 @@ enum_max(obj) } static VALUE +min_by_i(i, memo) + VALUE i; + NODE *memo; +{ + VALUE v; + + v = rb_yield(i); + if (NIL_P(memo->u1.value)) { + memo->u1.value = v; + memo->u2.value = i; + } + else if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo->u1.value), v, memo->u1.value) < 0) { + memo->u1.value = v; + memo->u2.value = i; + } + return Qnil; +} + +/* + * call-seq: + * enum.min_by {| obj| block } => obj + * + * Returns the object in <i>enum</i> that gives the minimum + * value from the given block. + * + * a = %w(albatross dog horse) + * a.min_by {|x| x.length } #=> "dog" + */ + +static VALUE +enum_min_by(obj) + VALUE obj; +{ + VALUE result; + NODE *memo = rb_node_newnode(NODE_MEMO, Qnil, 0, 0); + + rb_iterate(rb_each, obj, min_by_i, (VALUE)memo); + result = memo->u2.value; + rb_gc_force_recycle((VALUE)memo); + return result; +} + +static VALUE +max_by_i(i, memo) + VALUE i; + NODE *memo; +{ + VALUE v; + + v = rb_yield(i); + if (NIL_P(memo->u1.value)) { + memo->u1.value = v; + memo->u2.value = i; + } + else if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo->u1.value), v, memo->u1.value) > 0) { + memo->u1.value = v; + memo->u2.value = i; + } + return Qnil; +} + +/* + * call-seq: + * enum.max_by {| obj| block } => obj + * + * Returns the object in <i>enum</i> that gives the maximum + * value from the given block. + * + * a = %w(albatross dog horse) + * a.max_by {|x| x.length } #=> "albatross" + */ + +static VALUE +enum_max_by(obj) + VALUE obj; +{ + VALUE result; + NODE *memo = rb_node_newnode(NODE_MEMO, Qnil, 0, 0); + + rb_iterate(rb_each, obj, max_by_i, (VALUE)memo); + result = memo->u2.value; + rb_gc_force_recycle((VALUE)memo); + return result; +} + +static VALUE member_i(item, memo) VALUE item; NODE *memo; @@ -933,6 +1005,8 @@ Init_Enumerable() rb_define_method(rb_mEnumerable,"any?", enum_any, 0); rb_define_method(rb_mEnumerable,"min", enum_min, 0); rb_define_method(rb_mEnumerable,"max", enum_max, 0); + rb_define_method(rb_mEnumerable,"min_by", enum_min_by, 0); + rb_define_method(rb_mEnumerable,"max_by", enum_max_by, 0); rb_define_method(rb_mEnumerable,"member?", enum_member, 1); rb_define_method(rb_mEnumerable,"include?", enum_member, 1); rb_define_method(rb_mEnumerable,"each_with_index", enum_each_with_index, 0); |