这个问题是针对非常具体的情况,我可能会更改参数。这不是任何 Rails 应用程序的一部分。
参数是{:email => " ab", :xyz => " ", :opq => nil}
我运行以下:
params.each{|_, v| v.strip! if v}
params.keep_if{|_, v| v.length > 0 if v}
获取参数为
{:email => "ab"}
有没有将以上两行合并为一条?
这个问题是针对非常具体的情况,我可能会更改参数。这不是任何 Rails 应用程序的一部分。
参数是{:email => " ab", :xyz => " ", :opq => nil}
我运行以下:
params.each{|_, v| v.strip! if v}
params.keep_if{|_, v| v.length > 0 if v}
获取参数为
{:email => "ab"}
有没有将以上两行合并为一条?
ruby-1.9.3-p125 :011 > params ={:email => " ab", :xyz => " ", :opq => nil}
=> {:email=>" ab", :xyz=>" ", :opq=>nil}
ruby-1.9.3-p125 :012 > params.reject! { |_, v| !v || v.strip!.length == 0 }
=> {:email=>"ab"}
params.each{|_, v| v.strip! if v}.reject!{|_, v| !v || v.length == 0}
实际上,您编写的行是可链接的:
params.each{|_, v| v.strip! if v}.keep_if{|_, v| v.length > 0 if v}
这是有效的,因为each
返回对象本身(已更新)。但是,恕我直言,就地更新通常不是一个好主意,所以这里有一个实用的方法:
params2 = Hash[params.map { |k, v| [k, v.strip] if v && v.strip.size > 0 }.compact]
但这是不必要的冗长,因为 stdlib 缺乏一些基本的抽象。在它的帮助下Enumerable#mash
,Object#present?
它很简单:
params2 = params.mash { |k, v| [k, v.strip] if v.present? }
这是一个似乎在技术上回答您的问题的选项,但我猜这不是您想要的:
params.select{|_,v| v.strip.length > 0 if v}
您遇到的根本问题是 Hash#map 不返回哈希,而是返回数组。很多人,包括我自己,都觉得这很烦人。参见例如:http ://www.ruby-forum.com/topic/185611
这是一个使用注入的详细选项。
params.inject({}) {|h,(k,v)| h.merge(k => v ? v.strip : v)}.select{|_,v| v.length > 0 if v}
如果对您很重要,这些解决方案都不会对参数进行任何破坏性更改。
1.9.3-p125 :030 > params = {:email => " ab", :xyz => " ", :opq => nil}
=> {:email=>" ab", :xyz=>" ", :opq=>nil}
1.9.3-p125 :031 > params.inject({}) {|h,(k,v)| h.merge(k => v ? v.strip : v)}.select{|_,v| v.length > 0 if v}
=> {:email=>"ab"}
1.9.3-p125 :032 > params
=> {:email=>" ab", :xyz=>" ", :opq=>nil}
Inject 是一个棘手的功能,需要一些时间来适应。我将尝试逐步解释这一行:
params.inject({}}
说要创建一个空哈希来存储我们的结果。接下来它有点毛茸茸的。我将从里到外解开下一个命令。
v ? v.strip : v
使用三元运算符在 v 计算结果为 true 的情况下返回 v.strip 或在 v 为 false 或 nil 的情况下返回 v
k => v ? v.strip : v
用结果创建一个新的哈希
h.merge(k => v ? v.strip : v)
将我们的新哈希合并到一开始为空的 h 中,然后将结果传递给注入循环的下一次迭代。
在循环的下一次迭代中, h 将不再为空,未来的结果将继续合并到它上面。
此时我们已经剥离了哈希,如果我们在这里停止,结果如下所示:
1.9.3-p125 :032 > params
=> {:email=>" ab", :xyz=>" ", :opq=>nil}
1.9.3-p125 :033 > params.inject({}) {|h,(k,v)| h.merge(k => v ? v.strip : v)}
=> {:email=>"ab", :xyz=>"", :opq=>nil}
现在散列被剥离了,选择语句是直截了当的。我在这里使用 select 而不是 keep_if,因为尽管没有 !,keep_if 是一种破坏性方法。请参阅此咆哮: http://news.ycombinator.com/item?id= 2247352。由于我们的注入语句返回一个哈希值,我们可以直接调用.select
它,尽管我不建议在实际实践中让你的代码行这么长。
1.9.3-p125 :034 > params
=> {:email=>" ab", :xyz=>" ", :opq=>nil}
1.9.3-p125 :035 > params.inject({}) {|h,(k,v)| h.merge(k => v ? v.strip : v)}.select{|_,v| v.length > 0 if v}
=> {:email=>"ab"}
params.keys.each{|k| v = h.delete(k); h[k] = v.strip if v and !v.empty?}
或者
params.select!{|k, v| v and v.strip!; v and !v.empty?}