如何在Ruby中改进这个Array.select?

时间:2010-11-24 02:40:44

标签: ruby arrays

我刚写了这篇......可怕的Ruby代码,我想知道是否有更好的方法。

我有一个哈希数组,我想要一个哈希。我想要选择的“条件”是两个独立的数组 - 一个是键,另一个是值。如果数组中的哈希值对key == valuekeys中的每一对都有正确的values,我想返回该哈希值。

任何使代码更具可读性的指针?

arr = [
  {:foo => 'foo', :bar => 'bar', :baz => 'baz'},
  {:foo => 'bar', :bar => 'bar', :baz => 'bar'},
  {:foo => 'foo', :bar => 'foo', :baz => 'foo'},
]

keys = [:foo, :bar]
values  = ['foo', 'bar']

arr.select{|c| keys.map{|k| i = keys.index(k); c[keys[i]] == values[i]}.delete(false) != false}.first
# => {:foo => 'foo', :bar => 'bar', :baz => 'baz'}

2 个答案:

答案 0 :(得分:2)

您是否必须指定您要查找的键数组和值数组?如果你这样做,那么将它们转换为像这样的哈希:

hsh = Hash[*keys.zip(values).flatten]  #=> {:foo=>"foo", :bar=>"bar"}

然后选择如下:

arr.select { |c| c == c.merge(hsh) }   #=> [{:foo=>"foo", :bar=>"bar", :baz=>"baz"}]

如果您可以首先指定您正在寻找的哈希,那么您不需要第一行。

答案 1 :(得分:2)

arr = [
  {foo:'foo', bar:'bar', baz:'baz'},
  {foo:'bar', bar:'bar', baz:'bar'},
  {foo:'foo', bar:'foo', baz:'foo'},
]

keys = [:foo, :bar]
values = ['foo', 'bar']

p arr.find { |c|
    keys.zip(values).all? { |k,v|
        c[k] == v
    }
}
  1. 如果您将符号作为键,则可以使用{foo:'bar'}语法声明哈希值。
  2. 使用Enumerable#find查找第一次出现。