2017-06-06 51 views
0

我有一个哈希阵列,我想搜索,我想写一个方法,将选项哈希作为参数,并返回所有元素在数组可以动态匹配所有的键/值对,我很难搞清楚它。红宝石阵列#选择一个选项哈希匹配

my_array = [ 
    { 
    foo: 'a', 
    bar: 'b', 
    baz: 'c' 
    }, 
    { 
    foo: 1, 
    bar: 2, 
    baz: 3 
    }, 
    { 
    foo: 'A', 
    bar: 'B', 
    baz: 'C' 
    }, 
    { 
    foo: 11, 
    bar: 12, 
    baz: 13 
    } 
] 

# takes an opts hash and returns all elements for which all 
# all key/value pairs match 
def search_by(opts) 
    opts.each do |k, v| 
    self.select { |f| f[k] == f[v] } 
    end 
end 

my_array.search_by(foo: 'a', bar: 'b') 
# should return { foo: 'a', bar: 'b', baz: 'c' } 

我已经尝试了几种不同的方式来动态地组成一个块传递基于如此的相似问题#SELECT,但我还没有多少运气并没有能够准确找到这个用例。动态#选择多种条件而只需执行一次#选择的最佳方式是什么?

回答

0

您可能会试图将此过于复杂化。这个怎么样

my_array = [ 
    {foo: 'a', bar: 'b', baz: 'c'}, 
    {foo: 1, bar: 2, baz: 3}, 
    {foo: 'A', bar: 'B', baz: 'C'}, 
    {foo: 11, bar: 12, baz: 13} 
] 
finder = {foo: 'a', bar: 'b'} 
my_array.select {|h| h.values_at(*finder.keys) == finder.values } 
#=> [{:foo=>"a", :bar=>"b", :baz=>"c"}] 

Hash#values_at使用给定键返回而你的情况应在“Finder” Hash匹配这些键的值相应的值。

为了使其明确工作你解释,我们可以定义一个单身方法my_array这样的方式:

my_array.define_singleton_method(:search_by) do |opts| 
    self.select {|h| h.values_at(*opts.keys) == opts.values} 
end 

my_array.search_by(foo: 'a', bar: 'b') 
#=> [{:foo=>"a", :bar=>"b", :baz=>"c"}] 
my_array.search_by(foobar: 'n') 
#=> [] 
my_array << {foo: 11,bar: 15,baz: 'c'} 
my_array.search_by(foo: 11) 
#=>[{:foo=>11, :bar=>12, :baz=>13}, {:foo=>11, :bar=>15, :baz=>"c"}] 
+0

这是完美的,谢谢! –

1

您可以使用Hash#>=

返回true如果其他是集散列或等于散列

my_array.select { |h| h >= finder } 
#=> [{:foo=>"a", :bar=>"b", :baz=>"c"}] 
+0

你做了我的一天!我正要建议'my_array.select {| h | h.merge(finder)== h}',但你拥有的是完美的。 –