如何遍历Ruby数组并按指定关键词分类存储至新数组
实现方案
现有代码的核心问题是每次调用facts方法都会重新发起爬虫请求,资源浪费严重,我们先解决这个问题,再实现按关键词分类筛选的功能,无需额外新建类,只需在现有类中做少量修改即可。
代码修改示例
1. 优化爬虫方法,添加结果缓存
def facts # 已爬取过则直接返回缓存结果,避免重复请求网站 return @all_facts if defined?(@all_facts) && !@all_facts.empty? @all_facts = [] doc = Nokogiri::HTML(URI.open("https://www.funfactsabout.net/plant-facts/")) doc.css("ul.facts-list li").each do |list| @all_facts.push(list.text.strip) end @all_facts end
2. 新增分类映射与筛选方法
提前预设分类对应的匹配关键词组,后续新增分类直接修改映射表即可,无需改动筛选逻辑:
# 分类与匹配关键词映射,可按需扩展关键词 CATEGORY_KEYWORDS = { "树木" => ["树", "乔木", "灌木", "木本"], "花卉" => ["花", "花卉", "月季", "牡丹", "菊", "兰"], "食物" => ["食用", "蔬菜", "水果", "吃", "食材"] } # 分类筛选方法,传入分类名称返回匹配的所有科普内容 def filter_by_category(category) return [] unless CATEGORY_KEYWORDS.key?(category) keywords = CATEGORY_KEYWORDS[category] facts.select do |fact| keywords.any? { |kw| fact.include?(kw) } end end
3. 修改交互方法,支持分类查询
def more input_prompt = " 请输入1-#{facts.length}之间的数字获取对应植物科普,输入「树木」「花卉」「食物」获取对应分类内容,或输入'leave'退出: " while true puts input_prompt input = gets.strip # 按序号查询 if input.to_i > 0 && input.to_i <= facts.length puts facts[input.to_i - 1] # 按分类查询 elsif CATEGORY_KEYWORDS.key?(input) matched_facts = filter_by_category(input) if matched_facts.empty? puts "暂未找到#{input}相关的科普内容" else puts "--- 以下是#{input}相关科普 ---" matched_facts.each_with_index { |fact, idx| puts "#{idx+1}. #{fact}" } end # 退出逻辑 elsif input == "leave" puts goodbye return else puts "抱歉,我无法理解你的输入,请重新输入。" end end end
疑问解答
- 是否需要新建类:如果当前类就是负责植物科普相关逻辑,无需新建类;如果后续要扩展多来源科普、多分类管理等复杂功能,可以单独封装
PlantFactsManager类统一管理,现有需求无需额外拆分。 - 是否需要新建方法:建议保留独立的分类筛选方法,和原有爬虫、交互逻辑解耦,后续修改筛选规则、新增分类都不需要改动其他逻辑。
- 是否需要专门的数组名称:我们用实例变量
@all_facts缓存全量爬取结果,类内所有方法都可以直接调用,无需定义全局变量,也不会重复爬取。 - 高效实现方式:缓存爬虫结果避免重复请求是核心优化,筛选逻辑用Ruby内置的数组迭代方法,性能足够应对万条以内的数据量,无需额外优化;如果后续数据量过大,可以预先给所有内容打标签存储,不用每次查询都遍历。
内容的提问来源于stack exchange,提问作者Kiana
相关产品推荐
相关产品推荐

