Ruby匹配到目标项后如何继续循环迭代并差异化格式化输出
问题根因
你添加匹配逻辑后循环提前终止,由两个问题导致:
- 匹配命中的分支内误写了
break或return语句,直接触发循环退出 - 原有代码的计数器
n += 1写在条件分支内部,调整判断逻辑时很容易漏写递增,要么触发死循环要么导致遍历异常;另外原有跳过无效条目的分支没有写计数器递增,只要遇到名称、描述全为空的包就会死循环,之前能正常运行只是测试数据里没有这类无效条目。
实现方案
直接用Ruby原生的数组遍历方法each替代手动维护计数器的while循环,从根源上避免计数器写错的问题。遍历过程中对每个包单独做匹配判断,匹配项走特殊格式化逻辑,全程不添加中断循环的语句,就可以完整遍历所有包条目,不会因为找到匹配项提前终止。
完整实现代码:
def makelist(jsn, searchterm) jsn.each do |pkg| pkname = pkg["Name"] pkdesc = pkg["Description"] pkver = pkg["Version"] # 跳过名称、描述全为空的无效包 next if pkname.nil? && pkdesc.nil? # 按需调整匹配规则,示例为包名完全匹配,可改成大小写不敏感、模糊匹配、描述字段匹配等 is_exact_match = pkname == searchterm # 模糊匹配示例: # is_exact_match = pkname.to_s.downcase.include?(searchterm.downcase) || pkdesc.to_s.downcase.include?(searchterm.downcase) if is_exact_match # 匹配项走自定义特殊格式化,比如加高亮标记、调整fmt参数即可 puts "#{fmt(fmt("aur/", 6), 0)}#{fmt("(exact) ", 8)}#{fmt(pkname, 0)} [#{fmt(pkver, 8)}]\n #{pkdesc}" else # 普通项沿用原有格式化逻辑 puts "#{fmt(fmt("aur/", 6), 0)}#{fmt(pkname, 0)} [#{fmt(pkver, 8)}]\n #{pkdesc}" end end end
如果要保留原有while循环写法,必须把计数器递增逻辑移到所有条件分支外部,保证每轮循环不管走哪个分支都会正常递增:
def makelist(jsn, searchterm) len = jsn.length n = 0 while n < len do pkname = jsn[n]["Name"] pkdesc = jsn[n]["Description"] pkver = jsn[n]["Version"] # 有效条目才做输出判断 if !(pkname.nil? && pkdesc.nil?) is_exact_match = pkname == searchterm if is_exact_match puts "#{fmt(fmt("aur/", 6), 0)}#{fmt("(exact) ", 8)}#{fmt(pkname, 0)} [#{fmt(pkver, 8)}]\n #{pkdesc}" else puts "#{fmt(fmt("aur/", 6), 0)}#{fmt(pkname, 0)} [#{fmt(pkver, 8)}]\n #{pkdesc}" end end # 统一递增计数器,不要放到任何条件分支内部 n += 1 end end
注意事项
- 遍历逻辑中不要添加
break、return类的中断语句,就可以保证遍历完所有包条目 - 差异化格式化的规则可以按需调整,比如给匹配项加颜色、加Exact标记、调整缩进都不影响遍历逻辑
内容的提问来源于stack exchange,提问作者wreedb
相关产品推荐
相关产品推荐

