在Ruby中访问嵌套的哈希映射

时间:2016-12-13 18:23:34

标签: ruby hashmap

我有一个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"}]

我也希望能够在密钥之间进行聚合等事情。

3 个答案:

答案 0 :(得分: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]

P.S。

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

答案 1 :(得分:0)

迭代所有键,书籍和属性:

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

获取一个嵌套在Hashes / Arrays中的值:

如果您使用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"

答案 2 :(得分:-2)

您的内部哈希位于数组中。

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

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