【问题标题】:How can I pattern match on an array of hashes in Ruby 2.7?如何在 Ruby 2.7 中对哈希数组进行模式匹配?
【发布时间】:2021-01-07 22:30:45
【问题描述】:

我正在通过与JSON document 的模式匹配来试验new pattern matching feature in Ruby 2.7。我想用它来匹配具有某些特征的数组元素。在我的例子中,有一个区域数据数组存储为散列,每个散列都有一个 id。我只需要使用10id 来匹配哈希,如下所示:

require 'net/http'
require 'json'

HOSPITAL_DATA_URI = URI("https://www.dph.illinois.gov/sitefiles/COVIDHospitalRegions.json?nocache=1").freeze

hospital_data = JSON.parse(Net::HTTP.get(HOSPITAL_DATA_URI), symbolize_names: true)
region_values = hospital_data[:regionValues]

case region_values
  in [{id: 10, **unimportant_attributes}, **non_region_10_hashes]
    puts 'We found region 10!'
else
  puts 'aw shucks'
end

puts "...but Region 10 does exist" if region_values.find {|region| region[:id] == 10}

#=> aw shucks
#=> ...but Region 10 does exist

我希望它打印“我们找到区域 10!”但事实并非如此。

是否可以使用 Ruby 模式匹配来做到这一点?

【问题讨论】:

    标签: ruby pattern-matching ruby-2.7


    【解决方案1】:

    u/zvero_kha 有一个答案here。基本上我正在寻找的东西被称为“查找模式”,并且最近才被合并到 Ruby 中。预计将出现在 Ruby 3.0 版本中。在我的情况下,您将如何使用它:

    case region_values
      # Note the "splat-like" asterisks. These are the "find patterns."
      in [*, {id: 10} => r10, {id: 11} => r11, *]
        puts "Region 10: #{r10}"
        puts "Region 11: #{r11}"
        # Note that both r10 and r11 are available in this block of code here
    else
      puts 'aw shucks'
    end
    

    Matz's explanation 对于使用这些“查找模式”非常有用。

    【讨论】:

    • 感谢 Jörg 的编辑,这是一个意外的复制/粘贴!
    【解决方案2】:

    我们发现给定的代码检索到region_values 的以下值:

    region_values
      #=> [
        {:region=>"Region01", :id=>1, :region_description=>"1 - Rockford Region Hospitals",
         :ICUAvail=>126, :ICUCapacity=>234, :VentsAvailable=>296, :VentsCapacity=>359},
        {:region=>"Region02", :id=>2, :region_description=>"2 - Peoria Region Hospitals",
         :ICUAvail=>140, :ICUCapacity=>304, :VentsAvailable=>398, :VentsCapacity=>496},
        {:region=>"Region03", :id=>3, :region_description=>"3 - Springfield Region Hospitals",
         :ICUAvail=>77, :ICUCapacity=>150, :VentsAvailable=>350, :VentsCapacity=>410},
        {:region=>"Region04", :id=>4, :region_description=>"4 - Edwardsville Region Hospitals",
         :ICUAvail=>61, :ICUCapacity=>113, :VentsAvailable=>134, :VentsCapacity=>158},
        {:region=>"Region05", :id=>5, :region_description=>"5 - Marion Region Hospitals",
         :ICUAvail=>64, :ICUCapacity=>107, :VentsAvailable=>294, :VentsCapacity=>309},
        {:region=>"Region06", :id=>6, :region_description=>"6 - Champaign Region Hospitals",
         :ICUAvail=>70, :ICUCapacity=>162, :VentsAvailable=>260, :VentsCapacity=>287},
        {:region=>"Region07", :id=>7, :region_description=>"7 - Southwest Suburbs Region Hospitals",
         :ICUAvail=>175, :ICUCapacity=>484, :VentsAvailable=>444, :VentsCapacity=>589},
        {:region=>"Region08", :id=>8, :region_description=>"8 - West Suburbs Region Hospitals",
         :ICUAvail=>176, :ICUCapacity=>480, :VentsAvailable=>319, :VentsCapacity=>550},
        {:region=>"Region09", :id=>9, :region_description=>"9 - Northwest Suburbs Region Hospitals",
         :ICUAvail=>238, :ICUCapacity=>452, :VentsAvailable=>438, :VentsCapacity=>533},
        {:region=>"Region10", :id=>10, :region_description=>"10 - Northeast Suburbs Region Hospitals",
         :ICUAvail=>112, :ICUCapacity=>206, :VentsAvailable=>190, :VentsCapacity=>234},
        {:region=>"Region11", :id=>11, :region_description=>"11 - City of Chicago Region Hospitals",
         :ICUAvail=>395, :ICUCapacity=>1064, :VentsAvailable=>1392, :VentsCapacity=>1803}
    ]
    

    在发布此之前,我不知道 Ruby v2.7 中的新模式匹配功能。阅读this article 后,我真的不明白这如何适用于您的问题(尽管该功能本身很有趣并且似乎很有用)。你可以写:

    region_values.each do |h|
      puts case h
      in {id: 10}
        'We found region 10!'
      else
        'aw shucks'
      end
    end
    aw shucks
    aw shucks
    aw shucks
    aw shucks
    aw shucks
    aw shucks
    aw shucks
    aw shucks
    aw shucks
    We found region 10!
    aw shucks
    

    found = region_values.find do |h|
      case h
      in {id: 10}
        true
      end
    end
    
    puts found ? 'We found region 10!' : 'aw shucks'
    We found region 10!
    

    但新功能的应用都不是很有趣。

    【讨论】:

    • 是的,我认为“有趣的应用程序”是我想要找到的。老实说,我不知道何时使用模式匹配。感谢您的回答!
    猜你喜欢
    • 2011-07-25
    • 1970-01-01
    • 2014-03-05
    • 1970-01-01
    • 2011-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多