避免嵌套 select 块

Avoid nested select blocks

我必须从 json 文档中检索一些与电影和节目相关的信息。

unique_nos = js['navigation']['category'].select{|n|  n['name']=="Home"}.first['category'].select{|s| s['name']=="#{type}"}.first['category'].select{|k| k['name']=='Movie Studios'}.first['category'].map{|l| l['categoryId']}

电视节目也是如此。

unique_nos = js['navigation']['category'].select{|n|  n['name']=="Home"}.first['category'].select{|s| s['name']=='TV'}.first['category'].select{|k| k['name']=='Networks'}.first['category'].map{|l| l['categoryId']}

我想避免重复的代码执行相同的任务。我宁愿将此块作为参数传递,以便它可以是动态的。有什么方法可以通过元编程来实现吗?

您可以简单地将其提取为方法:

def find_unique_nos(js, type, category)
  js['navigation']['category'].select{|n| n['name']=="Home"}.first['category'].select{|s| s['name']== type }.first['category'].select{|k| k['name']==category}.first['category'].map{|l| l['categoryId']}
end

附带说明一下,select { ... }.first 等同于 find { ... },因此您可以将其简化为:

def find_unique_nos(js, type, category)
  js['navigation']['category'].find{|n| n['name'] == "Home" }['category']
                              .find{|s| s['name'] == type }['category']
                              .find{|k| k['name'] == category }['category']
                              .map{|l| l['categoryId']}
end

如果你想更复杂一些,你可以使用构建器来完成 find{ ... }['category']:

的重复工作
def find_unique_nos(js, type, category)
  ['Home', type, category].inject(js['navigation']['category']) do |cat, name|
     cat.find{|n| n['name'] == name }['category']
  end.map{|l| l['categoryId']}
end

请考虑使用中间变量来分解这么长的链,这将有助于简化调试和理解。使用相同的代码重新格式化:

def unique_numbers(json: j, type: t)
  category = type == 'TV' ? 'Networks' : 'Movie Studios'
  json['navigation']['category']
    .select{|n| n['name']=="Home"}
    .first['category']
    .select{|s| s['name'] == type }
    .first['category']
    .select{|k| k['name'] == category }
    .first['category']
    .map{|l| l['categoryId']}
end