如何在 ruby 上的散列中创建 deep_slice
how to make a deep_slice in a hash on ruby
我四处寻找一种干净的方法来做到这一点,我找到了一些解决方法,但没有找到类似切片的东西(有些人建议使用 gem 但我认为这个操作不需要,如果我错了,请纠正我),所以我发现自己有一个包含一堆哈希的哈希,我想要一种方法来对该哈希执行 Slice 操作并获得 key/value 对来自嵌套哈希,所以问题:
ruby中是否有类似deep_slice的内容?
示例:
input: a = {b: 45, c: {d: 55, e: { f: 12}}, g: {z: 90}}, keys = [:b, :f, :z]
expected output: {:b=>45, :f=>12, :z=>90}
提前致谢!
看了一段时间后,我决定自己实现,我是这样解决的:
a = {b: 45, c: {d: 55, e: { f: 12}}, g: {z: 90}}
keys = [:b, :f, :z]
def custom_deep_slice(a:, keys:)
result = a.slice(*keys)
a.keys.each do |k|
if a[k].class == Hash
result.merge! custom_deep_slice(a: a[k], keys: keys)
end
end
result
end
c_deep_slice = custom_deep_slice(a: a, keys: keys)
p c_deep_slice
上面的代码是由哈希 class.
提供的 classic DFS, which takes advantage of the merge!
你可以测试上面的代码here
require 'set'
def recurse(h, keys)
h.each_with_object([]) do |(k,v),arr|
if keys.include?(k)
arr << [k,v]
elsif v.is_a?(Hash)
arr.concat(recurse(v,keys))
end
end
end
hash = { b: 45, c: { d: 55, e: { f: 12 } }, g: { b: 21, z: 90 } }
keys = [:b, :f, :z]
arr = recurse(hash, keys.to_set)
#=> [[:b, 45], [:f, 12], [:b, 21], [:z, 90]]
请注意,hash
与问题中给出的示例哈希略有不同。我添加了第二个嵌套键 :b
来说明返回散列而不是键值对数组的问题。如果我们将 arr
转换为散列,则 [:b, 45]
对将被丢弃:
arr.to_h
#=> {:b=>21, :f=>12, :z=>90}
然而,如果需要,可以这样写:
arr.each_with_object({}) { |(k,v),h| (h[k] ||= []) << v }
#=> {:b=>[45, 21], :f=>[12], :z=>[90]}
我将 keys
从数组转换为集合只是为了加快查找速度 (keys.include?(k)
)。
如果散列包含嵌套散列数组以及嵌套散列,则可以使用稍微修改的方法。
我四处寻找一种干净的方法来做到这一点,我找到了一些解决方法,但没有找到类似切片的东西(有些人建议使用 gem 但我认为这个操作不需要,如果我错了,请纠正我),所以我发现自己有一个包含一堆哈希的哈希,我想要一种方法来对该哈希执行 Slice 操作并获得 key/value 对来自嵌套哈希,所以问题:
ruby中是否有类似deep_slice的内容?
示例:
input: a = {b: 45, c: {d: 55, e: { f: 12}}, g: {z: 90}}, keys = [:b, :f, :z]
expected output: {:b=>45, :f=>12, :z=>90}
提前致谢!
看了一段时间后,我决定自己实现,我是这样解决的:
a = {b: 45, c: {d: 55, e: { f: 12}}, g: {z: 90}}
keys = [:b, :f, :z]
def custom_deep_slice(a:, keys:)
result = a.slice(*keys)
a.keys.each do |k|
if a[k].class == Hash
result.merge! custom_deep_slice(a: a[k], keys: keys)
end
end
result
end
c_deep_slice = custom_deep_slice(a: a, keys: keys)
p c_deep_slice
上面的代码是由哈希 class.
提供的 classic DFS, which takes advantage of the merge!你可以测试上面的代码here
require 'set'
def recurse(h, keys)
h.each_with_object([]) do |(k,v),arr|
if keys.include?(k)
arr << [k,v]
elsif v.is_a?(Hash)
arr.concat(recurse(v,keys))
end
end
end
hash = { b: 45, c: { d: 55, e: { f: 12 } }, g: { b: 21, z: 90 } }
keys = [:b, :f, :z]
arr = recurse(hash, keys.to_set)
#=> [[:b, 45], [:f, 12], [:b, 21], [:z, 90]]
请注意,hash
与问题中给出的示例哈希略有不同。我添加了第二个嵌套键 :b
来说明返回散列而不是键值对数组的问题。如果我们将 arr
转换为散列,则 [:b, 45]
对将被丢弃:
arr.to_h
#=> {:b=>21, :f=>12, :z=>90}
然而,如果需要,可以这样写:
arr.each_with_object({}) { |(k,v),h| (h[k] ||= []) << v }
#=> {:b=>[45, 21], :f=>[12], :z=>[90]}
我将 keys
从数组转换为集合只是为了加快查找速度 (keys.include?(k)
)。
如果散列包含嵌套散列数组以及嵌套散列,则可以使用稍微修改的方法。