find_all数组中符合条件的元素?

时间:2014-02-05 00:33:13

标签: ruby-on-rails ruby

我有一个哈希条目数组,并希望根据传递给函数的参数进行过滤。

如果哈希中有三个值ABC,我想做类似的事情:

data = [{A:'a1', B:'b1', C:'c1'}, 
    {A:'a1', B:'b2', C:'c1'},
    {A:'a1', B:'b2', C:'c2'}, 
    {A:'a2', B:'b1', C:'c1'},
    {A:'a2', B:'b2', C:'c1'}]

data.find_all{ |d| d[:A].include?params[:A] }
    .find_all{ |d| d[:B].include?params[:B] }
    .find_all{ |d| d[:C].include?params[:C] }

找到所有A =='a1'和B ='b2'

的地方

所以对于上面我得到: {A:'a1',B:'b2',C:'c1'}和{A:'a1',B:'b2',C:'c2'} *添加if / else语句,如params.has_key? 'B',然后执行某些操作。 *每次将新类型的值添加到哈希映射时修改我的代码(比如现在我有'D')。

注意:哈希的键是一个符号,但值是一个字符串,我想做一个“包含”而不是“等于”。

我认为它是SQL Select语句,其中包含零或更多'=='子句

2 个答案:

答案 0 :(得分:15)

如果我正确理解了您的问题,那么我相信select课程的Array方法可能会对您有所帮助。

select获取一段代码,该代码块是数组中每个元素的测试条件。数组中满足该测试条件的任何元素都将被选中,结果是所选元素的数组。

例如:

arr = [ 4, 8, 15, 16, 23, 42 ]
result = arr.select { |element| element > 20 }
puts result   # prints out [23, 42]

在你的例子中,你有一个哈希数组,这使得它比我的带有简单数字数组的例子稍微复杂一些。在您的示例中,我们有:

data = [{A:'a1', B:'b1', C:'c1'}, 
        {A:'a1', B:'b2', C:'c1'},
        {A:'a1', B:'b2', C:'c2'}, 
        {A:'a2', B:'b1', C:'c1'},
        {A:'a2', B:'b2', C:'c1'}]

我相信您希望代码执行的操作类似于:从我的数据数组中选择所有哈希值,其中哈希值:A等于某个值,而:B等于某些值其他价值。

假设您要查找:A == 'a1':B == 'b2'所有哈希值。你会这样做:

data.select { |hash_element| hash_element[:A] == 'a1' && hash_element[:B] == 'b2' }

这一行返回一个数组,其中包含原始数据数组中的哈希值,这些哈希值满足我们在块中提供的条件 - 即:A == 'a1':B == 'b2'中的哈希值。希望这有助于解决你的问题!

此处有关select方法的更多信息:

http://www.ruby-doc.org/core-2.1.0/Array.html#method-i-select

已编辑 - 以下是对原始答案的补充

要跟进您之后关于if/else条款和添加新参数的问题......您传递给select的代码块当然可能比什么更复杂我在这个例子中写过。您只需记住这一点:如果代码块的最后一行的计算结果为true,则该元素将被选入结果数组。否则,它将不会被选中。

因此,这意味着您可以定义自己的函数,并在传递给select的条件块中调用该函数。例如,像这样:

def condition_test(hash_element, key_values)
    result = true
    key_values.each do |pair|
      if hash_element[pair[:key]] != pair[:value]
        result = false
      end
    end
    return result
end

# An example of the key-value pairs you might require to satisfy your select condition.
requirements = [ {:key => :A, :value => 'a1'},
                 {:key => :B, :value => 'b2'} ]

data.select { |hash_element| condition_test(hash_element, requirements) }

这使得您的条件阻止更加动态,而不是像我们在前面的示例中那样为:A == 'a1':B == 'b2'进行硬连接。您可以根据需要查找的键和值动态调整requirements。您还可以修改condition_test,而不仅仅是检查某个键的哈希值是否等于某个值。您可以在if/else中添加condition_test条款,以测试某些密钥的存在等内容。

答案 1 :(得分:0)