根据key => value删除嵌套的hash
Delete nested hash according to key => value
我有这个哈希:
response = '{"librairies":[{"id":1,"books":[{"id":1,"qty":1},{"id":2,"qty":3}]},{"id":2,"books":[{"id":1,"qty":0},{"id":2,"qty":3}]}]}'
其中我想删除至少其中一本书数量为空的所有图书馆。
例如,对于给定的 response
,我希望这样 return:
'{"librairies":[{"id":1,"books":[{"id":1,"qty":1},{"id":2,"qty":3}]}]}'
我试过这个:
parsed = JSON.parse(response)
parsed["librairies"].each do |library|
library["books"].each do |book|
parsed.delete(library) if book["qty"] == 0
end
end
但是这个 return 是完全相同的 response
哈希,没有删除第二个库(id => 2 的库)。
你可以用 Array#delete_if and Enumerable#any? 来做这个
# Move through each array element with delete_if
parsed["librairies"].delete_if do |library|
# evaluates to true if any book hash in the library
# has a "qty" value of 0
library["books"].any? { |book| book["qty"] == 0 }
end
希望对您有所帮助
为避免更改哈希 parsed
,您可以执行以下操作。
首先,让我们格式化 parsed
以便我们可以看到我们正在处理的内容:
parsed = { "libraries"=>[ { "id"=>1,
"books"=>[ { "id"=>1, "qty"=>1 },
{ "id"=>2, "qty"=>3 } ]
},
{ "id"=>2,
"books"=>[ { "id"=>1, "qty"=>0 },
{ "id"=>2, "qty"=>3 } ]
}
]
}
稍后我想证明在我们创建新哈希时 parsed
没有被更改。一个简单的方法是在 parsed
之前和之后计算哈希码,看看它是否发生变化。 (虽然不能 100% 确定不同的哈希值不会有相同的哈希码,但这里并不是什么值得大惊小怪的事情。)
parsed.hash
#=> 852445412783960729
我们首先需要制作一个parsed
的"deep copy",这样对副本的更改不会影响parsed
。一种方法是使用 Marshal 模块:
new_parsed = Marshal.load(Marshal.dump(parsed))
我们现在可以根据需要修改文案了:
new_parsed["libraries"].reject! { |h| h["books"].any? { |g| g["qty"].zero? } }
#=> [ { "id"=>1,
# "books"=>[ { "id"=>1, "qty"=>1 },
# { "id"=>2, "qty"=>3 }
# ]
# }
# ]
new_parsed # => { "libraries"=>[ { "id"=>1,
"books"=>[ { "id"=>1, "qty"=>1},
{ "id"=>2, "qty"=>3}
]
}
]
}
并且我们确认原始哈希没有改变:
parsed.hash
#=> 852445412783960729
我有这个哈希:
response = '{"librairies":[{"id":1,"books":[{"id":1,"qty":1},{"id":2,"qty":3}]},{"id":2,"books":[{"id":1,"qty":0},{"id":2,"qty":3}]}]}'
其中我想删除至少其中一本书数量为空的所有图书馆。
例如,对于给定的 response
,我希望这样 return:
'{"librairies":[{"id":1,"books":[{"id":1,"qty":1},{"id":2,"qty":3}]}]}'
我试过这个:
parsed = JSON.parse(response)
parsed["librairies"].each do |library|
library["books"].each do |book|
parsed.delete(library) if book["qty"] == 0
end
end
但是这个 return 是完全相同的 response
哈希,没有删除第二个库(id => 2 的库)。
你可以用 Array#delete_if and Enumerable#any? 来做这个
# Move through each array element with delete_if
parsed["librairies"].delete_if do |library|
# evaluates to true if any book hash in the library
# has a "qty" value of 0
library["books"].any? { |book| book["qty"] == 0 }
end
希望对您有所帮助
为避免更改哈希 parsed
,您可以执行以下操作。
首先,让我们格式化 parsed
以便我们可以看到我们正在处理的内容:
parsed = { "libraries"=>[ { "id"=>1,
"books"=>[ { "id"=>1, "qty"=>1 },
{ "id"=>2, "qty"=>3 } ]
},
{ "id"=>2,
"books"=>[ { "id"=>1, "qty"=>0 },
{ "id"=>2, "qty"=>3 } ]
}
]
}
稍后我想证明在我们创建新哈希时 parsed
没有被更改。一个简单的方法是在 parsed
之前和之后计算哈希码,看看它是否发生变化。 (虽然不能 100% 确定不同的哈希值不会有相同的哈希码,但这里并不是什么值得大惊小怪的事情。)
parsed.hash
#=> 852445412783960729
我们首先需要制作一个parsed
的"deep copy",这样对副本的更改不会影响parsed
。一种方法是使用 Marshal 模块:
new_parsed = Marshal.load(Marshal.dump(parsed))
我们现在可以根据需要修改文案了:
new_parsed["libraries"].reject! { |h| h["books"].any? { |g| g["qty"].zero? } }
#=> [ { "id"=>1,
# "books"=>[ { "id"=>1, "qty"=>1 },
# { "id"=>2, "qty"=>3 }
# ]
# }
# ]
new_parsed # => { "libraries"=>[ { "id"=>1,
"books"=>[ { "id"=>1, "qty"=>1},
{ "id"=>2, "qty"=>3}
]
}
]
}
并且我们确认原始哈希没有改变:
parsed.hash
#=> 852445412783960729