ruby中的哈希中没有完全发生值替换

ruby中的哈希中没有完全发生值替换,ruby,hash,Ruby,Hash,下面的代码片段根据散列中的类型更新值,它几乎按预期工作,但我仍然惊讶地看到Fixnum类型没有得到完全更新,我得到的是下面的输出 输出: { :vad_val => "test", :enabled => nil, :reg_id => nil, :buffer_value => 54, :direct => "test", :direct_val => "test", :de

下面的代码片段根据散列中的类型更新值,它几乎按预期工作,但我仍然惊讶地看到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"
}
从原始数据可以清楚地看出,reg_id和connections是Fixnum,因此预期为54,但它仍然被nil替换,当class为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
{“reg_id”:{“Type”:“Fixnum”,“Mutable”:true,“Value”:null}

所以在If语句中

v[“Value”]。class==Fixnum

因为
nil.class==NilClass
,所以变为False。因此,在您的情况下,您不应该以这种方式检查它:

v[“Value”]。class==Fixnum

但是

在代码的上述部分中,如果v.class是哈希,则检查“value”。对于连接哈希,连接[“value”]为null,而不是Fixnum

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

这就是原因,您将获得空值。

我不知道您试图实现什么,但您的方法是错误的。让我粘贴工作代码:

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
也就是说,输入数据包含两个
已启用的
键和≈10
decision
s。代码取最后一个,这是毫无意义的。因此,您试图得到的最终结果毫无意义,因为它会混淆值


尽管如此,我想我还是给出了一些进一步的提示。

旁注:我们不需要比较
var.class==class
,而是使用
var.is_?class
和/或
class==var
。它也给了我之前得到的相同结果。这是旁注。结果不会有什么不同。我也尝试了同样的结果没用。我也试着用类似的支票代替我的整张支票,但没有用,我得到了完全出乎意料的结果:(.1票赞成你:)。这是我的错,我没有在引号中指定Fixnumber,现在它可以正常工作了。@user2997518您应该更加小心地处理这个类。Strings、NilClass、Ruby chars等。这是一篇非常简单的文章,但如果没有这些知识,您将来会遇到很多这样的情况。谢谢,我会处理好的。在我的回复中这种类型被认为是一个字符串,另一方面,我的实现能够实现90%的预期结果,因为对于string和true类,只有当值为null时,它才是完全功能的,只有当值为null时,它才是不功能的。谢谢你的建议,但我不想要所有的东西,这就是为什么到目前为止进行了此筛选,并且它可以正常工作的原因很好。那么上面的代码对你有用。请注意,在你的示例中,数据
reg_id
connections
的值为零,尽管它们被称为
Fixnum
s的实例,并且在结果中它们似乎被解释为
0
s。这就是我无法将该值设置为其他fixnumber的原因rs无论我在哪里设置值,所有就绪的现有值都存在,但由于maxim提到的nill类,具有空值的fixnumber我不能这样做。因此理想情况下,我应该设置任意值(即54)使用reg_id和connection。除了0之外,您的代码是否能够为这两种类型设置任何值。当然。当'Fixnum'然后是Integer(el.last.last | | 0)时,请查看
周围的行
并将
|124; 0
更改为
|124; 54
。我希望您了解您正在做的事情,并且您知道这样一个事实,即一旦输入数据意外地在名为
连接的哈希中包含新键,一切都将被破坏。您如何执行相同的操作,我就能够执行您的第一个函数仅对ap parse_hash进行了说明,但不确定,因为它给出了错误,因为它在ruby中不是有效的语法,第一个函数只需给出如下类型的列表,[[“vad_val”,“String”,“0001”]]
                "connections": {
                "Type": "Fixnum",
                "Mutable": true,
                "Value": null
            }
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"
}