mirror of
https://github.com/ruby/ruby.git
synced 2026-01-27 04:24:23 +00:00
Array#rfind
Implement Array#rfind, which is the same as find except from the other side of the Array. Also implemented Array#find (as opposed to the generic one on Enumerable because it is significantly faster and to keep the implementations together. [Feature #21678]
This commit is contained in:
parent
4f900e3ce9
commit
6147b69587
Notes:
git
2025-12-12 18:35:56 +00:00
95
array.c
95
array.c
@ -2088,6 +2088,99 @@ rb_ary_fetch(int argc, VALUE *argv, VALUE ary)
|
||||
return RARRAY_AREF(ary, idx);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* find(if_none_proc = nil) {|element| ... } -> object or nil
|
||||
* find(if_none_proc = nil) -> enumerator
|
||||
*
|
||||
* Returns the first element for which the block returns a truthy value.
|
||||
*
|
||||
* With a block given, calls the block with successive elements of the array;
|
||||
* returns the first element for which the block returns a truthy value:
|
||||
*
|
||||
* (0..9).find {|element| element > 2} # => 3
|
||||
*
|
||||
* If no such element is found, calls +if_none_proc+ and returns its return value.
|
||||
*
|
||||
* (0..9).find(proc {false}) {|element| element > 12} # => false
|
||||
* {foo: 0, bar: 1, baz: 2}.find {|key, value| key.start_with?('b') } # => [:bar, 1]
|
||||
* {foo: 0, bar: 1, baz: 2}.find(proc {[]}) {|key, value| key.start_with?('c') } # => []
|
||||
*
|
||||
* With no block given, returns an Enumerator.
|
||||
*
|
||||
*/
|
||||
|
||||
static VALUE
|
||||
rb_ary_find(int argc, VALUE *argv, VALUE ary)
|
||||
{
|
||||
VALUE if_none;
|
||||
long idx;
|
||||
|
||||
RETURN_ENUMERATOR(ary, argc, argv);
|
||||
if_none = rb_check_arity(argc, 0, 1) ? argv[0] : Qnil;
|
||||
|
||||
for (idx = 0; idx < RARRAY_LEN(ary); idx++) {
|
||||
VALUE elem = RARRAY_AREF(ary, idx);
|
||||
if (RTEST(rb_yield(elem))) {
|
||||
return elem;
|
||||
}
|
||||
}
|
||||
|
||||
if (!NIL_P(if_none)) {
|
||||
return rb_funcallv(if_none, idCall, 0, 0);
|
||||
}
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* rfind(if_none_proc = nil) {|element| ... } -> object or nil
|
||||
* rfind(if_none_proc = nil) -> enumerator
|
||||
*
|
||||
* Returns the last element for which the block returns a truthy value.
|
||||
*
|
||||
* With a block given, calls the block with successive elements of the array in
|
||||
* reverse order; returns the last element for which the block returns a truthy
|
||||
* value:
|
||||
*
|
||||
* (0..9).rfind {|element| element < 5} # => 4
|
||||
*
|
||||
* If no such element is found, calls +if_none_proc+ and returns its return value.
|
||||
*
|
||||
* (0..9).rfind(proc {false}) {|element| element < -2} # => false
|
||||
* {foo: 0, bar: 1, baz: 2}.rfind {|key, value| key.start_with?('b') } # => [:baz, 2]
|
||||
* {foo: 0, bar: 1, baz: 2}.rfind(proc {[]}) {|key, value| key.start_with?('c') } # => []
|
||||
*
|
||||
* With no block given, returns an Enumerator.
|
||||
*
|
||||
*/
|
||||
|
||||
static VALUE
|
||||
rb_ary_rfind(int argc, VALUE *argv, VALUE ary)
|
||||
{
|
||||
VALUE if_none;
|
||||
long len, idx;
|
||||
|
||||
RETURN_ENUMERATOR(ary, argc, argv);
|
||||
if_none = rb_check_arity(argc, 0, 1) ? argv[0] : Qnil;
|
||||
|
||||
idx = RARRAY_LEN(ary);
|
||||
while (idx--) {
|
||||
VALUE elem = RARRAY_AREF(ary, idx);
|
||||
if (RTEST(rb_yield(elem))) {
|
||||
return elem;
|
||||
}
|
||||
|
||||
len = RARRAY_LEN(ary);
|
||||
idx = (idx >= len) ? len : idx;
|
||||
}
|
||||
|
||||
if (!NIL_P(if_none)) {
|
||||
return rb_funcallv(if_none, idCall, 0, 0);
|
||||
}
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* find_index(object) -> integer or nil
|
||||
@ -8816,6 +8909,8 @@ Init_Array(void)
|
||||
rb_define_method(rb_cArray, "length", rb_ary_length, 0);
|
||||
rb_define_method(rb_cArray, "size", rb_ary_length, 0);
|
||||
rb_define_method(rb_cArray, "empty?", rb_ary_empty_p, 0);
|
||||
rb_define_method(rb_cArray, "find", rb_ary_find, -1);
|
||||
rb_define_method(rb_cArray, "rfind", rb_ary_rfind, -1);
|
||||
rb_define_method(rb_cArray, "find_index", rb_ary_index, -1);
|
||||
rb_define_method(rb_cArray, "index", rb_ary_index, -1);
|
||||
rb_define_method(rb_cArray, "rindex", rb_ary_rindex, -1);
|
||||
|
||||
@ -3584,6 +3584,23 @@ class TestArray < Test::Unit::TestCase
|
||||
assert_equal((1..67).to_a.reverse, var_0)
|
||||
end
|
||||
|
||||
def test_find
|
||||
ary = [1, 2, 3, 4, 5]
|
||||
assert_equal(2, ary.find {|x| x % 2 == 0 })
|
||||
assert_equal(nil, ary.find {|x| false })
|
||||
assert_equal(:foo, ary.find(proc { :foo }) {|x| false })
|
||||
end
|
||||
|
||||
def test_rfind
|
||||
ary = [1, 2, 3, 4, 5]
|
||||
assert_equal(4, ary.rfind {|x| x % 2 == 0 })
|
||||
assert_equal(1, ary.rfind {|x| x < 2 })
|
||||
assert_equal(5, ary.rfind {|x| x > 4 })
|
||||
assert_equal(nil, ary.rfind {|x| false })
|
||||
assert_equal(:foo, ary.rfind(proc { :foo }) {|x| false })
|
||||
assert_equal(nil, ary.rfind {|x| ary.clear; false })
|
||||
end
|
||||
|
||||
private
|
||||
def need_continuation
|
||||
unless respond_to?(:callcc, true)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user