Ruby中YAML数据站点匹配条件失效问题求助
问题分析与解决方案
你的代码核心问题出在数据类型不匹配上,这是Ruby中符号(Symbol)与字符串(String)最容易踩的典型坑!
问题根源
当你用YAML.load_file加载yml文件时,文件里带冒号前缀的:washington、:briston这类内容,会被自动解析成Ruby的**Symbol类型**(比如:washington)。但你调用calc方法时传入的是带引号的字符串(比如':washington'),测试循环里用的也是纯字符串'washington'——符号和字符串在Ruby里是完全独立的对象,所以h['begin'] == start永远返回false,导致tmp一直为nil,直接触发break unless tmp`,自然没有任何输出结果。
具体修复方案
方案1:调用方法时传入符号(推荐)
直接把调用参数改成Symbol类型,去掉引号即可:
a = Train.new("my_path_to.yml") a.calc(begin: :washington, end: :tokyo)
方案2:让方法兼容字符串输入
如果希望支持字符串形式的参数,在calc方法里把输入转换为Symbol:
class Train require 'yaml' def initialize(time) @time = YAML.load_file(time) end def calc(begin:, end:) ary = @time['time'] start = begin.to_sym # 统一转换为符号 stop = end.to_sym res = [] loop do tmp = ary.find { |h| h['begin'] == start } break unless tmp res << tmp start = tmp['end'] break if start == stop end res # 明确返回结果,Ruby方法默认返回最后一行,加上更清晰 end end
修复测试循环
你之前的for循环测试也犯了同样的类型错误,改成符号对比就能匹配成功:
ary = @time['time'] for i in ary if i['begin'] == :washington # 用符号和YAML解析后的内容对比 puts "good" else puts "no way" end end
额外优化建议
你的loop写法虽然不会无限循环(找不到下一站时tmp为nil会触发break),但可以改成更Ruby化的写法:
def calc(begin:, end:) start = begin.to_sym stop = end.to_sym current = start path = [] until current == stop segment = @time['time'].find { |h| h['begin'] == current } break unless segment path << segment current = segment['end'] end path end
内容的提问来源于stack exchange,提问作者user9409769
相关产品推荐
相关产品推荐

