提供Ruby阵列选择一个动态块
我有一组哈希。 这是一个典型值的小样本:
[{"id"=>1,
"context"=>"r178",
"asset"=>"Art Schools Hub",
"campaign"=>"Fashion Careers",
"contact_email"=>"evert_nolan@hammechaefer.net",
"notes"=>"",
"user_first_name"=>"Agustin",
"user_last_name"=>"Welch",
"status"=>"Completed",
"date_collected"=>"01/22/16"},
{"id"=>4,
"context"=>"r178",
"asset"=>"Art Schools Hub",
"campaign"=>"Graphic Design Careers",
"contact_email"=>"jamil_brakus@effertz.biz",
"notes"=>"",
"user_first_name"=>"Agustin",
"user_last_name"=>"Welch",
"status"=>"In Progress",
"date_collected"=>"01/22/16"},
{"id"=>15,
"context"=>"r178",
"asset"=>"Art Schools Hub",
"campaign"=>"Art Education",
"contact_email"=>"miss_kyle_mccullough@hicklezboncak.net",
"notes"=>"",
"user_first_name"=>"Jermaine",
"user_last_name"=>"Wilkinson",
"status"=>"Open",
"date_collected"=>"01/22/16"}]
我知道做这样的选择:
results = @network.select { |x| x["campaign"] == "Art Education" && x["status"] == "Open" }
过滤返回散列数组的数组,其中所选键具有搜索值。
但是,用户必须能够基于任何或所有具有用户提交的值的键过滤此数组。
虽然我可以用表单的params中的值代替块,如下所示:
results = @network.select { |x| x[params[1]["column"]] == params[1]["search"] && x[params[2]["column"]] == params[2]["search"] }
每个选择的逻辑可能不同。 可以有多达10个不同的条件,列值和搜索值的形式为params。
我需要一种方法根据用户提交的条件在选择的块部分动态创建表达式。
不幸的是,我试图为块构造一个表达式的每种方式都会导致无法通过select进行评估的字符串值。
我已经为此工作了好几天,所以如果有人能给我一个解决方案,我会非常感激。
编辑:由于Wand Maker的优雅的解决方案,我根据他的代码进行了以下修改,以允许用户基于搜索值以用户提交的值开头的键过滤散列数组,而不是等于值:
pm = params.map { |h| {h["column"] => h["search"].downcase} }.reduce(&:merge)
result = @network.select do |h|
temp = h.slice(*pm.keys)
new_temp = Hash.new
temp.each do |k,v|
new_temp[k]=v.downcase.slice(0..pm[k].length - 1)
end
new_temp == pm
end
现在这个效果很好。
这是一种可能的方法。
让我们定义params
为:
params = [{"column" => "context", "search" => "r178"},
{"column" => "campaign", "search" => "Art Education"}]
我们将对它进行处理,使其在结构上类似@network
的元素。
pm = params.map { |h| {h["column"] => h["search"]} }.reduce(&:merge)
#=> {"context"=>"r178", "campaign"=>"Art Education"}
现在,我们将选择存在于这个处理过的params散列pm
的键,并使用它来从@network
数组中获取每个元素的切片,并且如果处理过的params散列和切片散列都相等,那么我们有一个匹配,我们可以选择该项目。
result = @network.select {|h| h.slice(*pm.keys) == pm}
完整的代码示例,我已经添加了require "active_support/core_ext/hash"
以便下面的程序可以作为独立的ruby程序运行,以便进行说明。 在Rails代码中不需要它。
require "pp"
require "active_support/core_ext/hash"
@network = [{"id"=>1, "context"=>"r178", "asset"=>"Art Schools Hub", "campaign"=>"Fashion Careers", "contact_email"=>"evert_nolan@hammechaefer.net", "notes"=>"", "user_first_name"=>"Agustin", "user_last_name"=>"Welch", "status"=>"Completed", "date_collected"=>"01/22/16"},
{"id"=>4, "context"=>"r178", "asset"=>"Art Schools Hub", "campaign"=>"Graphic Design Careers", "contact_email"=>"jamil_brakus@effertz.biz", "notes"=>"", "user_first_name"=>"Agustin", "user_last_name"=>"Welch", "status"=>"In Progress", "date_collected"=>"01/22/16"},
{"id"=>15, "context"=>"r178", "asset"=>"Art Schools Hub", "campaign"=>"Art Education", "contact_email"=>"miss_kyle_mccullough@hicklezboncak.net", "notes"=>"", "user_first_name"=>"Jermaine", "user_last_name"=>"Wilkinson", "status"=>"Open", "date_collected"=>"01/22/16"}]
params = [{"column" => "context", "search" => "r178"},
{"column" => "campaign", "search" => "Art Education"}]
pm = params.map { |h| {h["column"] => h["search"]} }.reduce(&:merge)
pp result = @network.select {|h| h.slice(*pm.keys) == pm}
#=> [{"id"=>15,
# "context"=>"r178",
# "asset"=>"Art Schools Hub",
# ...
# "status"=>"Open",
# "date_collected"=>"01/22/16"}]
关于在评论中寻求的澄清,该解决方案也可以适用于starts_with
类型的条件。 可以使用:
pp result = @network.select {|h| pm.keys.all?{|k| h[k].starts_with? pm[k]}}
链接地址: http://www.djcxy.com/p/10203.html