Ruby 3中的Hash解构

s5a0g9ez  于 2023-10-17  发布在  Ruby
关注(0)|答案(4)|浏览(128)

在Ruby 2中,您可以执行以下操作:

my_hash = {a: {aa: 1, ab: 2, ac: 3}}

my_hash.each do |key, aa:, ab: 4, **|
  puts key
  puts aa
  puts ab
end

在Ruby 3中,这将导致missing keywords :aa, :ab。在Ruby 3中重构这样的代码的最佳方法是什么?
类似下面的内容将不起作用,因为它不支持设置默认值:

my_hash.each do |key, values|
  values in {aa: aa, ab: ab}
end

我能想到的最好的方法是将现有的代码放在一个 Package 器中:

lambda = ->(key, aa:, ab: 4, **) do
  puts key
  puts aa
  puts ab
end

my_hash.each do |key, values|
  lambda.call(key, **values)
end

有更好的选择吗?

yv5phkfx

yv5phkfx1#

我想不出一种方法来转换散列到关键字参数。
但是为什么不使用散列的方式,即。而不像对待关键字一样对待它的键?除非您的实际代码更复杂,否则fetch似乎可以实现您想要的功能:

my_hash = {a: {aa: 1, ab: 2, ac: 3}}

my_hash.each do |key, values|
  puts key
  puts values.fetch(:aa)
  puts values.fetch(:ab, 4)
end

上面的代码在Ruby 2和Ruby 3中都可以很好地工作。就像你的例子一样,如果缺少:aa,它将引发一个错误,如果缺少:ab,它将使用默认值4

jobtbby3

jobtbby32#

如果你不需要使用默认值,而只需要销毁哈希,你可以使用=>运算符来处理pattern matching

my_hash = { a: { aa: 1, ab: 2, ac: 3 } }

my_hash.each do |key, values|
  values => { aa:, ab:, ac: }

  puts key, aa, ab, ac
end

如果values不包含所有键,则此代码将引发NoMatchingPatternKeyError

gfttwv5a

gfttwv5a3#

使用||

正如@Stefan所说,如果值可以包含nilfalse,则它将不起作用

my_hash = {a: {aa: 1, ac: 3}}
 
my_hash.each do |key, values|
  puts key
  puts values[:aa]
  puts values[:ab] || 4
end

使用key?

my_hash = {a: {aa: 1, ac: 3}}
default_values_hash = { :ab => 4 }
 
my_hash.each do |key, values|
  puts key
  puts values[:aa]
  puts values.key?(:ab) ? values[:ab] : default_values_hash[:ab]
end

使用default

my_hash = {a: {aa: 1, ab: 2, ac: 3}}

my_hash.each do |key, values|
  values.default = :notfound
  puts key
  puts values[:aa]
  puts values[:ab] == :notfound ? 4 : values[:ab]
end
my_hash = {a: {aa: 1, ac: 3}}
 
my_hash.each do |key, values|
  values.default = :notfound
  puts key
  puts values[:aa]
  puts values[:ab] == :notfound ? 4 : values[:ab]
end

使用default-proc

my_hash = {a: {aa: 1, ab: 2, ac: 3}}
default_values_hash = { :ab => 4 }

my_hash.each do |key, values|
  values.default_proc = proc { |hash, key| default_values_hash[key] || :notfound }
  puts key
  puts values[:aa]
  puts values[:ab]
end

使用merge

my_hash = {a: {aa: 1, ac: 3}}
default_values_hash = { :ab => 4 }
 
my_hash.each do |key, values|
  values = default_values_hash.merge(values)
  puts key
  puts values[:aa]
  puts values[:ab]
end

上面的代码在Ruby 2和Ruby 3中都可以运行

**注意:**我建议使用key?方法来测试和检查key是否存在,并相应地处理这种情况,因为与其他需要内部额外步骤的情况相比,它会快得多。

yi0zb3m4

yi0zb3m44#

我们可以将每个值赋给一个变量,然后检查它是否是哈希值,然后我们可以在内部循环中再次打印这些值

my_hash = {a: { aa: 1, ab: 2, ac:3 }}
may_hash.each do |key, value|
  puts key
  if value.kind_of(Hash)
    value.each do |inner_key, inner_value|
      puts inner_key
      puts inner_value
    end
  else
    puts value
  end
end

这样,我们可以同时重构外部哈希和内部哈希。

相关问题