【问题标题】:Accessing nested hash map in Ruby在 Ruby 中访问嵌套的哈希映射
【发布时间】:2016-12-13 18:23:34
【问题描述】:

我有一个 csv 格式的平面数据结构,我已将其转换为哈希,从而在文件中的一列上设置一个键...所以我们有 key_1、key_2、Key_3,每个键都有相关的值相关行

这是一个平面文件的例子……

key     book  id    ccy  mtm      161205 161206 161207 161208 161209
key_1   abc   123   usd  2000000  -5045  600    494    -2646  -231
key_2   abc   124   gbp  -150000  5178   20669  -1871  214    22251
key_3   abc   125   eur  1908055  -23279 -730   -513   -19933 -21555

这就是我创建哈希后的样子……

{"key_1"=>
   [{:book=>"abc",
     :trade_id=>"123",
     :ccy=>"usd",
     :mtm=>2000000,
     :"161205"=>-5045,
     :"161206"=>600,
     :"161207"=>494,
     :"161208"=>-2646,
     :"161209"=>-231}],
"key_2"=>
   [{:book=>"abc",
     :trade_id=>"124",
     :ccy=>"gbp",
     :mtm=>-150000,
     :"161205"=>5178,
     :"161206"=>20669,
     :"161207"=>-18771,
     :"161208"=>214,
     :"161209"=>22251}],
 "key_3"=>
   [{:book=>"abc",
     :trade_id=>"125",
     :ccy=>"eur",
     :mtm=>1908055,
     :"161205"=>-23279,
     :"161206"=>-730,
     :"161207"=>-513,
     :"161208"=>19933,
     :"161209"=>-21555}]}

我遇到的问题是我似乎无法访问嵌套哈希。我希望能够钻入哈希......所以像这样......

p h.select { |key| key == "key_3" } [ :ccy, :mtm " ]

会给我一个类似...的输出

[{"eur","1908055"}]

我还希望能够跨键进行聚合等操作。

【问题讨论】:

    标签: ruby hashmap


    【解决方案1】:
    a['key_3']               # [{:book=>"abc", :trade_id=>"125", :ccy=>"eur", :mtm=>1908055, :"161205"=>-23279, :"161206"=>-730, :"161207"=>-513, :"161208"=>19933, :"161209"=>-21555}]
      .first                 # {:book=>"abc", :trade_id=>"125", :ccy=>"eur", :mtm=>1908055, :"161205"=>-23279, :"161206"=>-730, :"161207"=>-513, :"161208"=>19933, :"161209"=>-21555}
      .values_at(:ccy, :mtm) # ["eur", 1908055]
    #=> ["eur", 1908055]
    

    编辑

    要通过嵌套键遍历哈希和映射,请使用Enumerable#map

    a.map { |_k, v| v.first[:mtm] }
    #=> [2000000, -150000, 1908055]
    a.map {|k, v| v.first[:"161205"]}
    #=> [-5045, 5178, -23279]
    

    附言

    {"eur","1908055"} 不是 Ruby 中的有效对象。

    【讨论】:

    • 行得通!谢谢。是否可以使用类似的方法来访问所有密钥并拉取数据?
    • 这很好,但由于某种原因,它对我不起作用......例如,一旦我添加 [:mtm],我就会收到关于 from (irb):650:in 的错误`block in irb_binding'...也许我不能在 irb 中使用它?如果我这样做 a.map { |_k, v| v.first } 它打印整个地图。
    • @antimuon 它应该在 irb、pry 和其他地方。仔细检查拼写:)
    • 我想我知道我做错了什么...我试图“查找”多个值,例如 v.first[:book, :mtm]...我使用 var 对其进行了扩展。地图 { |_k, v| v.first.values_at(:book, :mtm) } 返回多个值。谢谢!
    【解决方案2】:

    遍历所有键、书和属性:

    h.each do |key, books|
      puts key
      books.each do |book|
        # Use values_at to define variables
        name, trade_id, price, currency = book.values_at(:book, :trade_id, :mtm, :ccy)
    
        puts "#{name} : #{price} #{currency} (#{trade_id})"
    
        # or iterate over all key/values :
        book.each do |attribute, value|
          puts "#{attribute} : #{value}"
        end
    
        puts
      end
    end
    

    它输出:

    key_1
    abc : 2000000 usd (123)
    book : abc
    trade_id : 123
    ccy : usd
    mtm : 2000000
    161205 : -5045
    161206 : 600
    161207 : 494
    161208 : -2646
    161209 : -231
    
    key_2
    abc : -150000 gbp (124)
    book : abc
    trade_id : 124
    ccy : gbp
    mtm : -150000
    161205 : 5178
    161206 : 20669
    161207 : -18771
    161208 : 214
    161209 : 22251
    
    key_3
    abc : 1908055 eur (125)
    book : abc
    trade_id : 125
    ccy : eur
    mtm : 1908055
    161205 : -23279
    161206 : -730
    161207 : -513
    161208 : 19933
    161209 : -21555
    

    获取一个值,嵌套在哈希/数组中:

    如果您使用的是 Ruby 2.3,这对 dig 来说是一项完美的工作:

    h.dig("key_3", 0, :ccy) # => "eur"
    h.dig("key_3", 0, :mtm) # => 1908055
    

    它通过哈希和数组“钻取”,如果找不到对象,您不必担心错误:

    h.dig("key_4", 0, :ccy) # => nil
    

    您可以将它与values_at&. 结合使用,以实现安全导航和多个值。如果找不到对象,则不应引发异常:

    h.dig("key_3", 0)&.values_at(:ccy, :mtm) #=> ["eur", 1908055]
    price, currency = h.dig("key_3", 0)&.values_at(:mtm, :ccy)
    price # => 1908055
    currency # => "eur"
    

    【讨论】:

    • dig 很好,但 AFAIK 不会返回多个键的值 (:ccy, :mtm...)
    • 是的。我用&.values_at 更新了这个例子。谢谢。
    • 我使用的是 2.25,所以我不能使用 dig,但我会使用 2.3 进行检查。
    【解决方案3】:

    你的内部哈希在一个数组中。

    first 将获取数组的第一个元素

    h['key_3'].first.values_at(:ccy, :mtm) 可以工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-31
      • 2011-08-12
      • 1970-01-01
      • 2013-12-18
      相关资源
      最近更新 更多