在递归函数中将条件作为 Proc/Lambda/Block 传递会导致它在 lambda 内部的条件评估为真后退出。为什么?
Passing a condition as a Proc/Lambda/Block in recursive function causes it to exit once the condition inside the lambda has evaluated to true. Why?
所以我想创建一个递归函数,当给定一个数组时,将 return 满足条件的元素数组传递给函数。我尝试过使用 lambda、块和 proc,并且每次当条件计算结果为真时它们退出函数,而不是在满足基本情况时。我想知道这是为什么以及我该如何克服它。
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
编辑:
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 }
这是一些适合您的工作代码:
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]
有两个主要修复:
- 基本情况是
idx == arr.count
,而不是 idx == arr.count - 1
。如果 idx 越界,您只想在此处 return - arr.count - 1
是 在范围内 ,所以如果您在这种情况下 return ,您将跳过最后一次迭代。
- 你需要将最后的
find_by_condition_recur
调用移到 if findBy.call
块之外,否则递归将在条件失败时立即停止(并且数组的其余部分将不会被处理).
除此之外,我还进行了一些重构:
- 参数的默认值。没有理由必须在第一次调用方法时指定
idx
或 acc
参数——我们知道它们将分别是 0
和 []
所以让我们将这些设置为默认值。
- Block 应该始终是最后一个参数,否则您将迫使调用者使用丑陋的 proc/lambda 文字。使用 blocks 更加地道,而且只有当它是最后一个参数时才可以使用 blocks。
- 使用
idx
而不是 count
作为变量名,这样更准确。
所以我想创建一个递归函数,当给定一个数组时,将 return 满足条件的元素数组传递给函数。我尝试过使用 lambda、块和 proc,并且每次当条件计算结果为真时它们退出函数,而不是在满足基本情况时。我想知道这是为什么以及我该如何克服它。
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
编辑:
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 }
这是一些适合您的工作代码:
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]
有两个主要修复:
- 基本情况是
idx == arr.count
,而不是idx == arr.count - 1
。如果 idx 越界,您只想在此处 return -arr.count - 1
是 在范围内 ,所以如果您在这种情况下 return ,您将跳过最后一次迭代。 - 你需要将最后的
find_by_condition_recur
调用移到if findBy.call
块之外,否则递归将在条件失败时立即停止(并且数组的其余部分将不会被处理).
除此之外,我还进行了一些重构:
- 参数的默认值。没有理由必须在第一次调用方法时指定
idx
或acc
参数——我们知道它们将分别是0
和[]
所以让我们将这些设置为默认值。 - Block 应该始终是最后一个参数,否则您将迫使调用者使用丑陋的 proc/lambda 文字。使用 blocks 更加地道,而且只有当它是最后一个参数时才可以使用 blocks。
- 使用
idx
而不是count
作为变量名,这样更准确。