So I want to create a recursive function that, when given an array, will return an array of elements that meet the condition passed into the function. I have tried using lambdas, blocks and procs, and every time they exit the function once that condition evaluates to true, rather than when the base case is met. I want to know why this is and how I can overcome it.
def find_by_condition_recur(arr, count, acc, &block)
return acc if count == arr.count - 1
puts count
puts arr.count
if block.call(arr[count])
acc << arr[count]
else
find_by_condition_recur(arr, count += 1, acc, &block)
end
end
EDIT:
def find_by_condition_recur(arr, findBy, count, acc)
return acc if count == arr.count - 1
puts count
puts arr.count
if findBy.call(arr[count])
acc << arr[count]
find_by_condition_recur(arr, findBy, count += 1, acc)
end
end
search_condition = Proc.new { |x| x % 3 == 0 }
Here is some working code for you:
def find_by_condition_recur(arr, idx=0, acc=[], &findBy)
return acc if idx == arr.count
if findBy.call(arr[idx])
acc << arr[idx]
end
find_by_condition_recur(arr, idx + 1, acc, &findBy)
end
find_by_condition_recur([1,2,3]) { |num| num != 2 }
# => [1,3]
There were two major fixes:
idx == arr.count
, not idx == arr.count - 1
. You only want to return here if the idx is out-of-bounds - arr.count - 1
is in bounds, so if you return in that case, you would skip the last iteration.find_by_condition_recur
call to outside of the if findBy.call
block, otherwise recursion will stop as soon as the condition fails (and the rest of the array won't be processed).Other than that there were a few refactorings I made:
idx
or acc
arguments the first time the method is called - we know are they are going to be 0
and []
respectively so let's just set those as the default values.idx
instead of count
as the variable name, this is just more accurate.