使用新的 Ruby 模式匹配来检查哈希是否具有某些键

Using new Ruby pattern matching to check if a hash has certain keys

我想在这个非常简单的案例中使用新的 Ruby 3 功能。我知道这一定是可能的,但我还没有从文档中弄清楚。

给定一个散列,我想检查它是否有特定的键。我不介意它是否还有其他人。我想通过模式匹配来做到这一点(或者知道这是不可能的。)我也不想使用看起来过大的 case 语句。

{name: "John", salary: 12000, email: "john@email.com" } 
  1. 如果散列没有名称,并且电子邮件为字符串,薪水为数字,则引发错误。

  2. 在 if 或其他条件中使用该结构?

  3. 如果哈希以字符串作为键(这是我从 JSON.parse 得到的)怎么办?

    {“姓名”=>“约翰”,“薪水”=> 12000,“电子邮件”=>“约翰@email.com”}

您正在寻找 => 运算符:

h = {name: "John", salary: 12000, email: "john@email.com" }
h => {name: String, salary: Numeric, email: String} # => nil

增加一对 (test: 0):

h[:test] = 0
h => {name: String, salary: Numeric, email: String} # => nil

没有 :name 键:

h.delete :name
h => {name: String, salary: Numeric, email: String} # key not found: :name (NoMatchingPatternKeyError)

使用 :name 键但其值的 class 不匹配:

h[:name] = 1
h => {name: String, salary: Numeric, email: String} # String === 1 does not return true (NoMatchingPatternKeyError)

严格匹配:

h[:name] = "John"
h => {name: String, salary: Numeric, email: String} # => rest of {:test=>0} is not empty

in 运算符 returns 一个布尔值而不是引发异常:

h = {name: "John", salary: 12000, email: "john@email.com" }
h in {name: String, salary: Numeric, email: String} # => true
h[:name] = 1
h in {name: String, salary: Numeric, email: String} # => false

“我也不想使用看起来有点矫枉过正的 case 语句。” case 只是模式匹配的语法。据我所知,它与 case when 不同,它是 case in

h = {name: "John", salary: 12000, email: "john@email.com", other_stuff: [1] } 
case h
  in {name: String, salary: Integer, email: String}
    puts "matched"
  else
    raise "#{h} not matched"
end