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

Raz*_*aza 5 ruby ruby-on-rails

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

如果有哈希三个值A,BC,我想要做类似的东西:

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] }
Run Code Online (Sandbox Code Playgroud)

找到A =='a1'和B ='b2'的所有地方

所以对于上面我得到:{A:'a1',B:'b2',C:'c1'}和{A:'a1',B:'b2',C:'c2'}*put if/ elsestatements,喜欢params.has_key? 'B'做点什么.*每次将新类型的值添加到哈希映射时修改我的代码(比如现在我有'D').

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

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

Alv*_*Lee 17

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

select获取一个代码块,该代码块旨在作为数组中每个元素的测试条件.将选择数组中满足该测试条件的任何元素,结果是所选元素的数组.

例如:

arr = [ 4, 8, 15, 16, 23, 42 ]
result = arr.select { |element| element > 20 }
puts result   # prints out [23, 42]
Run Code Online (Sandbox Code Playgroud)

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

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'}]
Run Code Online (Sandbox Code Playgroud)

我相信您希望代码执行的操作类似于:从我的数据数组中选择所有散列,其中散列内:A等于某个值AND :B等于其他值.

假设你想要找到所有哈希的位置:A == 'a1':B == 'b2'.你会这样做:

data.select { |hash_element| hash_element[:A] == 'a1' && hash_element[:B] == 'b2' }
Run Code Online (Sandbox Code Playgroud)

这一行返回一个数组,其中包含原始数据数组中的哈希值,这些哈希值满足我们在块中提供的条件 - 也就是那些哈希值在哪里: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) }
Run Code Online (Sandbox Code Playgroud)

这使得你的条件阻塞更加动态,而不是硬连接:A == 'a1',:B == 'b2'就像我们在前面的例子中所做的那样.您可以requirements根据需要查找的键和值动态调整.您还可以修改condition_test除了检查某个键的哈希值是否等于某个值之外的其他功能.您可以在if/else子句中添加condition_test以测试某些键的存在等内容.