如何一次获取多个哈希值?

时间:2013-07-15 04:10:42

标签: ruby-on-rails ruby hash destructuring

这是什么缩短版本?:

from = hash.fetch(:from)
to = hash.fetch(:to)
name = hash.fetch(:name)
# etc

注意fetch,如果密钥不存在,我想引发错误。

必须有更短的版本,例如:

from, to, name = hash.fetch(:from, :to, :name) # <-- imaginary won't work

如果需要,可以使用ActiveSupport。

7 个答案:

答案 0 :(得分:88)

使用哈希的values_at方法:

from, to, name = hash.values_at(:from, :to, :name)

对于散列中不存在的任何键,这将返回nil

答案 1 :(得分:23)

Ruby 2.3最后为哈希引入了fetch_values方法,直接实现了这一点:

 <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="utf-8" />
            <link href="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.7.0/nv.d3.min.css" rel="stylesheet" />
            <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
            <script src="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.7.0/nv.d3.min.js"></script>
        </head>
        <body>
            
        <div id="coverage"><svg style="width:1200px;height:400px;"></svg></div>
        <script>
                coverage=[{"values": [{"y": 0.2, "x": 0}, {"y": 0.1, "x": 1}, {"y": 0.1, "x": 2}, {"y": 0.1, "x": 3}, {"y": 0.1, "x": 4}, {"y": 0.1, "x": 5}, {"y": 0.1, "x": 6}, {"y": 0.1, "x": 7}, {"y": 0.1, "x": 8}, {"y": 0.1, "x": 9}, {"y": 0.1, "x": 10}, {"y": 0.1, "x": 11}, {"y": 0.1, "x": 12}, {"y": 0.1, "x": 13}, {"y": 0.1, "x": 14}, {"y": 0.1, "x": 15}, {"y": 0.1, "x": 16}, {"y": 0.1, "x": 17}, {"y": 0.1, "x": 18}, {"y": 0.1, "x": 19}, {"y": 0.1, "x": 20}, {"y": 0.1, "x": 21}, {"y": 0.1, "x": 22}, {"y": 0.1, "x": 23}, {"y": 0.1, "x": 24}, {"y": 0.1, "x": 25}, {"y": 0.1, "x": 26}, {"y": 0.1, "x": 27}, {"y": 0.1, "x": 28}, {"y": 0.1, "x": 29}, {"y": 0.1, "x": 30}, {"y": 0.1, "x": 31}, {"y": 0.1, "x": 32}, {"y": 0.1, "x": 33}, {"y": 0.1, "x": 34}, {"y": 0.1, "x": 35}, {"y": 0.1, "x": 36}, {"y": 0.1, "x": 37}, {"y": 0.1, "x": 38}, {"y": 0.1, "x": 39}, {"y": 0.1, "x": 40}, {"y": 0.1, "x": 41}, {"y": 0.1, "x": 42}, {"y": 0.1, "x": 43}, {"y": 0.1, "x": 44}, {"y": 0.1, "x": 45}, {"y": 0.1, "x": 46}, {"y": 0.1, "x": 47}, {"y": 0.1, "x": 48}, {"y": 0.1, "x": 49}], "key": "qq003.1.3", "yAxis": "1"}, {"values": [{"y": 0.1, "x": 0}, {"y": 0.1, "x": 1}, {"y": 0.1, "x": 2}, {"y": 0.1, "x": 3}, {"y": 0.1, "x": 4}, {"y": 0.1, "x": 5}, {"y": 0.1, "x": 6}, {"y": 0.1, "x": 7}, {"y": 0.1, "x": 8}, {"y": 0.1, "x": 9}, {"y": 0.1, "x": 10}, {"y": 0.1, "x": 11}, {"y": 0.1, "x": 12}, {"y": 0.1, "x": 13}, {"y": 0.1, "x": 14}, {"y": 0.1, "x": 15}, {"y": 0.1, "x": 16}, {"y": 0.1, "x": 17}, {"y": 0.1, "x": 18}, {"y": 0.1, "x": 19}, {"y": 0.1, "x": 20}, {"y": 0.1, "x": 21}, {"y": 0.1, "x": 22}, {"y": 0.1, "x": 23}, {"y": 0.1, "x": 24}, {"y": 0.1, "x": 25}, {"y": 0.1, "x": 26}, {"y": 0.1, "x": 27}, {"y": 0.1, "x": 28}, {"y": 0.1, "x": 29}, {"y": 0.1, "x": 30}, {"y": 0.1, "x": 31}, {"y": 0.1, "x": 32}, {"y": 0.1, "x": 33}, {"y": 0.1, "x": 34}, {"y": 0.1, "x": 35}, {"y": 0.1, "x": 36}, {"y": 0.1, "x": 37}, {"y": 0.1, "x": 38}, {"y": 0.1, "x": 39}, {"y": 0.1, "x": 40}, {"y": 0.1, "x": 41}, {"y": 0.1, "x": 42}, {"y": 0.1, "x": 43}, {"y": 0.1, "x": 44}, {"y": 0.1, "x": 45}, {"y": 0.1, "x": 46}, {"y": 0.1, "x": 47}, {"y": 0.1, "x": 48}, {"y": 0.1, "x": 49}], "key": "qq003.1.67", "yAxis": "1"}, {"values": [{"y": 247677.0, "x": 0}, {"y": 250012.0, "x": 1}, {"y": 287416.0, "x": 2}, {"y": 327385.0, "x": 3}, {"y": 276739.0, "x": 4}, {"y": 247264.0, "x": 5}, {"y": 234246.0, "x": 6}, {"y": 252476.0, "x": 7}, {"y": 263584.0, "x": 8}, {"y": 244878.0, "x": 9}, {"y": 263238.0, "x": 10}, {"y": 223955.0, "x": 11}, {"y": 147838.0, "x": 12}, {"y": 216088.0, "x": 13}, {"y": 219334.0, "x": 14}, {"y": 464921.0, "x": 15}, {"y": 253147.0, "x": 16}, {"y": 143214.0, "x": 17}, {"y": 263756.0, "x": 18}, {"y": 289643.0, "x": 19}, {"y": 219631.0, "x": 20}, {"y": 280396.0, "x": 21}, {"y": 228272.0, "x": 22}, {"y": 205129.0, "x": 23}, {"y": 277684.0, "x": 24}, {"y": 336930.0, "x": 25}, {"y": 206536.0, "x": 26}, {"y": 184942.0, "x": 27}, {"y": 288391.0, "x": 28}, {"y": 265598.0, "x": 29}, {"y": 214029.0, "x": 30}, {"y": 205708.0, "x": 31}, {"y": 238413.0, "x": 32}, {"y": 173776.0, "x": 33}, {"y": 231737.0, "x": 34}, {"y": 189285.0, "x": 35}, {"y": 299765.0, "x": 36}, {"y": 254324.0, "x": 37}, {"y": 231075.0, "x": 38}, {"y": 425653.0, "x": 39}, {"y": 344885.0, "x": 40}, {"y": 394357.0, "x": 41}, {"y": 184156.0, "x": 42}, {"y": 251984.0, "x": 43}, {"y": 236977.0, "x": 44}, {"y": 280948.0, "x": 45}, {"y": 305699.0, "x": 46}, {"y": 249000.0, "x": 47}, {"y": 281287.0, "x": 48}, {"y": 247748.0, "x": 49}], "key": "qq001.2.047", "yAxis": "1"}];
    
    
            nv.addGraph(function() {
            var chart = nv.models.lineChart();
    
            chart.margin({top: 30, right: 60, bottom: 100, left: 60});
    
            var datum = coverage;
                    chart.xAxis
                    .rotateLabels(-25).tickFormat(d3.format(',.1f'));
                chart.yAxis
                    .axisLabel('Coverage').tickFormat(d3.format(',.02f'));
    
              chart.showLegend(true).useVoronoi(false);
                d3.select('#coverage svg')
                .datum(datum)
                .transition().duration(500)
                .attr('width', 1200)
                .attr('height', 400)
                .call(chart);
            });
    
        </script>
    
        </body>
    </html>

答案 2 :(得分:3)

hash = {from: :foo, to: :bar, name: :buz}

[:from, :to, :name].map{|sym| hash.fetch(sym)}
# => [:foo, :bar, :buz]
[:frog, :to, :name].map{|sym| hash.fetch(sym)}
# => KeyError

答案 3 :(得分:2)

my_array = {from: 'Jamaica', to: 'St. Martin'}.values_at(:from, :to, :name)
my_array.keys.any? {|key| element.nil?} && raise || my_array

这会引发您所要求的错误

 my_array = {from: 'Jamaica', to: 'St. Martin', name: 'George'}.values_at(:from, :to, :name)
 my_array.keys.any? {|key| element.nil?} && raise || my_array

这将返回数组。

但OP要求失败的钥匙失败......

class MissingKeyError < StandardError
end
my_hash = {from: 'Jamaica', to: 'St. Martin', name: 'George'}
my_array = my_hash.values_at(:from, :to, :name)
my_hash.keys.to_a == [:from, :to, :name] or raise MissingKeyError
my_hash = {from: 'Jamaica', to: 'St. Martin'}
my_array = my_hash.values_at(:from, :to, :name)
my_hash.keys.to_a == [:from, :to, :name] or raise MissingKeyError

答案 4 :(得分:1)

我想要的最简单的事情就是

from, to, name = [:from, :to, :name].map {|key| hash.fetch(key)}

或者,如果您要使用values_at,则可以使用带有默认值块的Hash

hash=Hash.new {|h, k| raise KeyError.new("key not found: #{k.inspect}") }
# ... populate hash
from, to, name = hash.values_at(:from, :to, :name) # raises KeyError on missing key

或者,如果你如此倾向,那么猴子补丁Hash

class ::Hash
  def fetch_all(*args)
    args.map {|key| fetch(key)}
  end
end
from, to, name = hash.fetch_all :from, :to, :name

答案 5 :(得分:1)

您可以使用默认值KeyError对象初始化哈希值。如果您尝试获取的密钥不存在,这将返回KeyError的实例。您需要做的就是检查它的(值)类,如果它是一个KeyError,则引发它。

hash = Hash.new(KeyError.new("key not found"))

让我们为这个哈希添加一些数据

hash[:a], hash[:b], hash[:c] = "Foo", "Bar", nil

最后查看值并在未找到密钥时引发错误

hash.values_at(:a,:b,:c,:d).each {|v| raise v if v.class == KeyError}

当且仅当密钥不存在时,这将引发异常。如果您有一个nil值的密钥,它不会抱怨。

答案 6 :(得分:0)

模式匹配是Ruby 2.7中的一项实验功能。

hash = { from: 'me', to: 'you', name: 'experimental ruby' }

hash in { from:, to:, name: }

请参见https://rubyreferences.github.io/rubyref/language/pattern-matching.html