【问题标题】:using ruby to extract the values in a hash in a DRY way使用 ruby​​ 以 DRY 方式提取哈希中的值
【发布时间】:2017-09-20 15:32:21
【问题描述】:

我的应用程序将 json_element 传递给不同的方法,其中的键是不同的,有时是空的。

为了处理它,我一直在使用以下示例代码对提取进行硬编码:

def act_on_ruby_tag(json_element)

begin

  # logger.progname        = __method__
  logger.debug             json_element

  code                   = json_element['CODE']['$'] unless json_element['CODE'].nil?
  predicate              = json_element['PREDICATE']['$'] unless json_element['PREDICATE'].nil?
  replace                = json_element['REPLACE-KEY']['$'] unless json_element['REPLACE-KEY'].nil?
  hash                   = json_element['HASH']['$'] unless json_element['HASH'].nil?

我想消除对值的硬编码,但不太确定如何。

我开始思考如下:

keys = json_element.keys
keys.each do |k|
        set_key = k.downcase
        instance_variable_set("@" + set_key, json_element[k]['$']) unless json_element[k].nil?
      end 

然后在方法的其余部分使用@code

我本来打算把它变成一个方法,然后替换掉所有这些硬编码的代码。

但我不完全确定这是否是一条好路。

【问题讨论】:

    标签: arrays json ruby each


    【解决方案1】:

    从具有{ code: ... } 之类的方法返回哈希结构几乎总是比设置任意实例变量更好。如果您将它们返回到一致的容器中,调用者就可以更轻松地处理将其交付到正确的位置、存储以供以后使用,或者挑选出他们想要的东西并丢弃其余的。

    尝试通过一系列更小、更轻的操作来打破一个大而笨重的步骤也是一个好主意。这使得代码更容易理解:

    def extract(json)
      json.reject do |k, v|
        v.nil?
      end.map do |k, v|
        [ k.downcase, v['$'] ]
      end.to_h
    end
    

    然后你得到这个:

    extract(
      'TEST' => { '$' => 'value' },
      'CODE' => { '$' => 'code' },
      'NULL' => nil
    )
    # => {"test"=>"value", "code"=>"code"}
    

    如果您想将整个内容作为实例变量持久化,这是一种相当典型的模式,但它会有一个可预测的名称,不受您正在使用的任意 JSON 文档的支配。

    另一种方法是将键硬编码为常量,例如:

    KEYS = %w[ CODE PREDICATE ... ]
    

    然后改用它,或者更进一步,在 YAML 或 JSON 文件中定义它,您可以读入以进行配置。这实际上取决于这些变化的频率,以及您对输入的不规则性有什么样的期望。

    【讨论】:

    • 谢谢...我意识到“$”实际上是使用 CobravsMongoose gem.BUT...真正的问题是您正在讨论的...拔出钥匙和在不出错的情况下检查是否有值。有时其中一个键没有价值——它是空的。这就是为什么我有nil? 支票。
    • Empty 和 nil? 是两个不同的东西,请记住这一点。如果您只是在寻找可以导航的内容,那么与v 进行测试就足够了。最少的代码通常更容易调试。
    【解决方案2】:

    这是一种更简洁的方式来完成原始代码的工作。

    code, predicate, replace, hash = json_element.values_at *%w{
      CODE PREDICATE REPLACE-KEY HASH
    }.map { |x| x.fetch("$", nil) if x }
    

    【讨论】:

    • 在这些情况下,我需要事先知道键是“代码、谓词、替换......等等”?这些每次都会改变......考虑提前知道是否有帮助时间......它可能......
    • 我怎样才能解析出这个——我也许可以在没有$ 工件的情况下创建它。
    • 这是一种在不使用元编程的情况下将 4 个特定键提取到顶级变量中的方法。在 ruby​​ 中,有很多方法可以做同样的事情
    猜你喜欢
    • 2019-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多