ruby中的哈希中没有完全发生值替换
下面的代码片段根据散列中的类型更新值,它几乎按预期工作,但我仍然惊讶地看到Fixnum类型没有得到完全更新,我得到的是下面的输出 输出:ruby中的哈希中没有完全发生值替换,ruby,hash,Ruby,Hash,下面的代码片段根据散列中的类型更新值,它几乎按预期工作,但我仍然惊讶地看到Fixnum类型没有得到完全更新,我得到的是下面的输出 输出: { :vad_val => "test", :enabled => nil, :reg_id => nil, :buffer_value => 54, :direct => "test", :direct_val => "test", :de
{ :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
也就是说,输入数据包含两个已启用的
键和≈10decision
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"
}