【问题标题】:Iterate over array while adding new elements to array在向数组添加新元素的同时迭代数组
【发布时间】:2020-03-05 14:14:02
【问题描述】:

我正在用 Ruby 编写一个网页抓取脚本,它会打开一个二手车网站,搜索汽车的品牌/型号,遍历结果页面,然后抓取每个页面上的数据。

我遇到的问题是我不一定知道一开始的最大页面数,只有当我迭代接近最后几个已知页面时,分页才会增加并显示更多页面。

我已将cleanpages 定义为一个数组,并用我所知道的首次打开网站时可用的页面填充它。然后我使用cleanpages.each do 来遍历那些“页面”。每次我在新页面上时,我都会将所有已知页面添加回cleanpages,然后运行cleanpages.uniq 以删除重复项。问题似乎在于cleanpages.each do 只迭代了其原始长度的次数。

我可以让它在each do 循环中增加它的迭代次数吗?

【问题讨论】:

  • 您是否有任何代码可以添加到您已经尝试过的问题中?见stackoverflow.com/help/how-to-ask
  • 您遇到问题的代码是什么?你的代码有什么问题?您收到错误消息吗?错误信息是什么?你得到的结果不是你期望的结果吗?你期望什么结果,为什么,你得到的结果是什么,两者有什么不同?您正在观察的行为不是期望的行为吗?期望的行为是什么,为什么,观察到的行为是什么,它们有何不同?请提供minimal reproducible example

标签: ruby iteration each


【解决方案1】:

尝试将数组用作队列,而不是使用 Array#each。总体思路是:

queue = initial_pages
while queue.any?
  page = queue.shift
  new_pages = process(page)
  queue.concat(get_unprocessed_pages(new_pages))
end

这里的想法是,您只需不断地从队列的头部取出项目,直到它为空。您可以在处理过程中将新项目推入队列末尾,它们将被正确处理。

您需要确保从 new_pages 中删除已在队列中或已处理的页面。

您也可以只保留数组数据结构,但手动保留指向列表中当前元素的指针。这样做的好处是可以维护完整的“已看到”页面列表,因此您可以在将剩余的任何内容附加到列表之前将它们从 new_pages 列表中删除:

index = 0
queue = initial_pages
while true do
  page = queue[index]
  break if page.nil?
  index += 1
  new_pages = get_new_pages(page) - queue
  queue.concat(new_pages)
end

【讨论】:

    猜你喜欢
    • 2016-11-30
    • 2018-06-29
    • 2018-03-12
    • 2015-04-30
    • 1970-01-01
    • 1970-01-01
    • 2018-08-02
    • 2011-02-20
    • 1970-01-01
    相关资源
    最近更新 更多