在ruby中,值替换不会完全发生在hash中

时间:2015-04-16 17:25:02

标签: ruby hash

下面的代码片段更新了基于哈希类型的值,它几乎按预期工作,但我仍然惊讶地看到Fixnum类型没有完全更新,我的输出低于输出。

输出:

{ :vad_val      => "test", 
  :enabled      => nil, 
  :reg_id       => nil, 
  :buffer_value => 54, 
  :direct       => "test", 
  :direct_val   => "test", 
  :decision     => "test", 
  :number       => 54, 
  :connections  => nil, 
  :threads      => 54, 
  :updates      => nil, 
  :severity     => 54, 
  :levelval     => 54, 
  :facility     => 54, 
  :depend       => "test"
}

从raw_data可以清楚地看到,reg_id和连接是Fixnum所以54是预期的但仍然被nil替换,当类为TrueClass时需要设置nil。这是一个非常小的事情,但作为一个新手,我无法弄清楚。

    #!/usr/bin/ruby
    require 'json'

raw_data = '{"method_name":"My function","success":true,"payload":[{"Type":"SM::Mod::Elu","Properties":{"TVset":{"Type":"Array","Mutable":false,"Value":[{"Type":"SM::Mod::VirtualArea","Properties":{"vad_val":{"Type":"String","Mutable":false,"Value":"0001"},"enabled":{"Type":"TrueClass","Mutable":false,"Value":true}},"Children":{"Music":{"Type":"SM::Mod::Base","Properties":{"reg_id":{"Type":"Fixnum","Mutable":true,"Value":null},"buffer_value":{"Type":"Fixnum","Mutable":true,"Value":10},"special_handling_table":{"Type":"SM::Mod::SpecialHandlingTable","Properties":{"behaviors_val":{"Type":"Hash","Mutable":false,"Value":{"1":{"Type":"Array","Mutable":false,"Value":[{"Type":"SM::Mod::Replace","Properties":{"direct":{"Type":"String","Mutable":true,"Value":"From"}},"Children":{}},{"Type":"SM::Mod::Behavior","Properties":{"direct_val":{"Type":"String","Mutable":true,"Value":"From"}},"Children":{}}],"IsActiveChange":null},"2":{"Type":"Array","Mutable":false,"Value":[{"Type":"SM::Mod::ReplaceSH","Properties":{"decision":{"Type":"String","Mutable":true,"Value":"Fromnetwork"}},"Children":{}}],"IsActiveChange":null},"3":{"Type":"Array","Mutable":false,"Value":[{"Type":"SM::Mod::DropBehavior","Properties":{"decision":{"Type":"String","Mutable":true,"Value":"Fromnetwork"}},"Children":{}}],"IsActiveChange":null},"4":{"Type":"Array","Mutable":false,"Value":[{"Type":"SM::Mod::StripHeaderres","Properties":{"decision":{"Type":"String","Mutable":true,"Value":"ToTransport"}},"Children":{}},{"Type":"SM::Mod::DropBehavior","Properties":{"decision":{"Type":"String","Mutable":true,"Value":"FromTransport"}},"Children":{}}],"IsActiveChange":null},"5":{"Type":"Array","Mutable":false,"Value":[{"Type":"SM::Mod::StripHeaderBehavior","Properties":{"decision":{"Type":"String","Mutable":true,"Value":"Tosnmp"}},"Children":{}},{"Type":"SM::Mod::DropBehavior","Properties":{"decision":{"Type":"String","Mutable":true,"Value":"FromTransport"}},"Children":{}}],"IsActiveChange":null},"6":{"Type":"Array","Mutable":false,"Value":[{"Type":"SM::Mod::ReplaceSHBehavior","Properties":{"decision":{"Type":"String","Mutable":true,"Value":"Fromconn"}},"Children":{}}],"IsActiveChange":null},"7":{"Type":"Array","Mutable":false,"Value":[{"Type":"SM::Mod::Dropfem","Properties":{"decision":{"Type":"String","Mutable":true,"Value":"FromTransport"}},"Children":{}}],"IsActiveChange":null},"8":{"Type":"Array","Mutable":false,"Value":[{"Type":"SM::Mod::Dropfem","Properties":{"decision":{"Type":"String","Mutable":true,"Value":"From"}},"Children":{}}],"IsActiveChange":null},"9":{"Type":"Array","Mutable":false,"Value":[{"Type":"SM::Mod::DropBehavior","Properties":{"decision":{"Type":"String","Mutable":true,"Value":"From"}},"Children":{}}],"IsActiveChange":null}},"IsActiveChange":null}},"Children":{}}},"Children":{}}}}],"IsActiveChange":null},"number":{"Type":"Fixnum","Mutable":false,"Value":0,"IsActiveChange":false},"connections":{"Type":"Fixnum","Mutable":true,"Value":null},"threads":{"Type":"Fixnum","Mutable":true,"Value":4},"updates":{"Type":"TrueClass","Mutable":true,"Value":null},"severity":{"Type":"Fixnum","Mutable":true,"Value":3},"levelval":{"Type":"Fixnum","Mutable":true,"Value":3},"facility":{"Type":"Fixnum","Mutable":true,"Value":3},"trace":{"Type":"smode::Depval::Fallback","Properties":{"enabled":{"Type":"TrueClass","Mutable":true,"Value":false},"depend":{"Type":"String","Mutable":false,"Value":""}},"Children":{}}},"Children":{}}],"error":""}'

    def create_hash(set, result = {})
      if set.class == Hash # iterate through hash
    #result.compare_by_identity

    set.each do |k, v|
          if v.class == Hash && %w(String TrueClass Fixnum).include?((v["Type"] || ''))
            result[k.to_sym] = v["Value"] # add this key's value to the output array
            if v["Value"].class==String

              result[k.to_sym]="test"
            elsif v["Value"].class==Fixnum
              result[k.to_sym]=54
            else v["Value"].class==TrueClass
              result[k.to_sym]=nil
            end
          elsif v.class == Hash || v.class == Array
            result = create_hash(v, result) # check nested arrays and hashes
          end
        end
      elsif set.class == Array
        set.each do |a|
          result = create_hash(a, result) # check elements of an array
        end
      end
      result
    end

    val = create_hash(JSON.parse(raw_data))
    p val

3 个答案:

答案 0 :(得分:1)

  

{"reg_id":{"Type":"Fixnum","Mutable":true,"Value":null}

所以在If语句中

  

v["Value"].class == Fixnum

错误,因为nil.class == NilClass。所以在你的情况下你应该检查它不是这样的:

  

v["Value"].class == Fixnum

但是

v["Type"] == "Fixnum"

答案 1 :(得分:1)

        if v["Value"].class==String
          result[k.to_sym]="test"
        elsif v["Value"].class==Fixnum
          result[k.to_sym]=54
        else v["Value"].class==TrueClass
          result[k.to_sym]=nil
        end

在代码的上方部分,您正在检查"值"如果v.class是哈希。对于连接哈希,连接["值"]为空,而不是Fixnum。

                "connections": {
                "Type": "Fixnum",
                "Mutable": true,
                "Value": null
            }

这就是原因,你对它不予理会。

答案 2 :(得分:1)

我不知道你想要实现什么,但你的做法是错误的。让我粘贴工作代码:

json = JSON.parse raw_data

def parse_hash hash
  hash.inject([]) { |memo, kv|
    next memo unless kv.last.is_a?(Enumerable)

    if kv.last.is_a? Array
      kv.last.each { |kv|
        memo += parse_hash kv
      }
    else
      if kv.last.has_key?('Type') && 
         kv.last.has_key?('Value') && 
         !kv.last['Value'].is_a?(Enumerable)
        memo << [kv.first, [kv.last['Type'], kv.last['Value']]]
      end

      memo += parse_hash kv.last
    end
    memo
  }
end

听起来我们抓住了我们想要的任何东西。但是等等:

ap parse_hash(json).map { |el|
  value = case el.last.first
          when 'Fixnum' then Integer(el.last.last || 0)
          when 'TrueClass' then !!el.last.last
          else el.last.last
          end
  [el.first.to_sym, value]
}.inject({}) { |memo, el|
  if memo.has_key?(el.first)
    memo[el.first] = [memo[el.first]] unless memo[el.first].is_a? Array
    memo[el.first] << el.last
  else
    memo[el.first] = el.last
  end
  memo
}

给我们:

{
  :buffer_value => 10,
   :connections => 0,
      :decision => [
    [0] "Fromnetwork",
    [1] "Fromnetwork",
    [2] "ToTransport",
    [3] "FromTransport",
    [4] "Tosnmp",
    [5] "FromTransport",
    [6] "Fromconn",
    [7] "FromTransport",
    [8] "From",
    [9] "From"
  ],
        :depend => "",
        :direct => "From",
    :direct_val => "From",
       :enabled => [
    [0] true,
    [1] false
  ],
      :facility => 3,
      :levelval => 3,
        :number => 0,
        :reg_id => 0,
      :severity => 3,
       :threads => 4,
       :updates => false,
       :vad_val => "0001"
}

也就是说,输入数据包含两个enabled键和≈10decision s。代码自愿采取最后一个,这是无稽之谈。所以,你试图得到的最终结果毫无意义,因为它会使价值变得混乱。

尽管如此,我想我提供了一些关于进一步发展的提示。