【问题标题】:Can't get recursive method to work无法使用递归方法
【发布时间】:2016-08-05 03:28:17
【问题描述】:

我有以下方法:

def all(response = nil, options = {}, data = [])
  response ||= get(resource_path, options)
  parsed_response = JSON.parse(response.body)
  return bad_response(response) unless response.code == '200'

  data += parsed_response['data'].nil? ? [] : parsed_response['data'].map { |obj| new(obj) }
  puts data.count
  if parsed_response.dig('additional_data', 'pagination', 'more_items_in_collection')

    options[:start] = parsed_response.dig('additional_data', 'pagination', 'next_start')
    all(nil, options, data) # recursively calls itself, passing cumulated data
  end
  puts data.count # WHY WOULD IT NOT JUST RETURN ONCE, BUT INSTEAD GO DOWN TO INITIAL VALUE?
  data
end

我对这种方法的问题是,何时退出该方法: (if parsed_response.dig('additional_data', 'pagination', 'more_items_in_collection') 返回false 并且应该触发最后一个方法的行),它开始倒带..

输出是:

Pipedrive::Customer.all.count
100
200
300
400
500
600
700
800
900
1000
1100
1200
1300
1400
1500
1600
1700
1800
1900
2000
2100
2200
2300
2400
2500
2600
2700
2800
2900
3000
3100
3200
3300
3400
3500
3600
3700
3800
3900
3991
3991
3900
3800
3700
3600
3500
3400
3300
3200
3100
3000
2900
2800
2700
2600
2500
2400
2300
2200
2100
2000
1900
1800
1700
1600
1500
1400
1300
1200
1100
1000
900
800
700
600
500
400
300
200
100
=> 100

这看起来很疯狂,但我希望我只是遗漏了一些非常简单的东西(确实是这样,但究竟是什么:))。

编辑

我的问题是 方法的结果,而不是 puts 本身。我希望Pipedrive::Customer.all.count 返回3991,但它返回100...有什么想法吗?我已经尝试将最后一行(data)放入else

  def all(response = nil, options = {}, data = [])
    response ||= get(resource_path, options)
    parsed_response = JSON.parse(response.body)
    return bad_response(response) unless response.code == '200'

    data += parsed_response['data'].nil? ? [] : parsed_response['data'].map { |obj| new(obj) }
    if parsed_response.dig('additional_data', 'pagination', 'more_items_in_collection')

      options[:start] = parsed_response.dig('additional_data', 'pagination', 'next_start')
      all(nil, options, data)
    else
      data
    end
    data 
  end

- 它仍然返回 100..

【问题讨论】:

  • 我在这里没有看到基本情况...
  • @Anthony 当集合中没有更多项目时,基本情况看起来是这样,在这种情况下parsed_response.dig(...) 将返回false;我认为安德烈打算将puts data.count; data 放在else 块中
  • 所以在编辑后all 现在返回data,但是你不会对递归调用的返回值做任何事情。换句话说,你返回data,然后把它丢在厨房地板上。
  • 终于搞定了!谢谢@pjs
  • 如果您只想要更新后的data,请在最后的end 声明之前取出data。使用 if-else,您将获得由对 all 的递归调用返回的 data,或者由 else 案例处理的 data。否则,保存来自all 的返回并在离开当前调用之前对其进行处理。

标签: ruby pipedrive-api


【解决方案1】:

问题是你在递归调用后没有退出函数,所以当它从递归调用返回时,它会继续并完成函数,因此每次递归调用都会第二次调用puts data.count出去。颠倒的顺序与函数堆栈有关。您的代码结构如下:

all:
  puts 100
  all:
    puts 200
    all:
      puts 300
      all:
        ...
      puts 300
    puts 200
  puts 100
done

根据您的代码,我认为您打算将第二个 putsdata 放在 else 中吗?那应该做你想做的事,虽然我没有完全理解你的代码

【讨论】:

    【解决方案2】:

    您只需要并且希望方法中有一个puts 语句。现在你将它告诉puts data.count,然后进行递归计算,然后从这些递归计算返回puts data.count 再次。在这两个puts 之间,递归调用将注入他们自己的puts 结果来来去去。这就是为什么它似乎在建立,然后解体。积累是puts's 进去,倒带是从puts's 递归调用之后。

    【讨论】:

    • 感谢回复!我的主要问题不在 puts (puts 只是为了尝试跟踪),-问题是该方法返回 100 而不是 3991 (就像我所做的 Pipedrive::Customer.all.count)..
    • @AndreyDeineko 这在您的问题中找不到,您只讨论了打印输出所示的解开问题。澄清您的问题似乎是有必要的。
    • 我的错,抱歉不清楚 - 编辑了问题!
    猜你喜欢
    • 1970-01-01
    • 2017-07-29
    • 2011-11-03
    • 1970-01-01
    • 2014-01-24
    • 2021-10-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多