这个问题是针对一个非常特定的情况,我可能会更改参数。这不是任何Rails应用程序的一部分。
params是{:email =>“ ab”,:xyz =>“ ”,:opq => nil}
,我运行以下命令:
params.each{|_, v| v.strip! if v}
params.keep_if{|_, v| v.length > 0 if v}
如何将参数合并为{:email => "ab"}
?
有没有一种方式可以将上述两行代码合并成一行?
这个问题是针对一个非常特定的情况,我可能会更改参数。这不是任何Rails应用程序的一部分。
params是{: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"}
strip!
来匹配提问者所需的值。 - Casey Fosterab = params.select { |_, v| v && v.strip.length > 0 }
然后 params = ab
所以仍然是两行。 - JVKparams = params.select ..
(所以仍然只有一行,没有令人讨厌的偷偷摸摸的副作用) - user166390params.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}
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为真时返回v.strip,在v为假或nil时返回v。
k => v ? v.strip : v
创建一个新的哈希表并返回结果。
h.merge(k => v ? v.strip : v)
将我们的新哈希表合并到最初为空的h中,并将结果传递给inject循环的下一次迭代。
在循环的下一次迭代中,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
,但我不建议在实际操作中将代码行变得如此长。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?}
params
对象是一种不好的编程方式。建议使用返回新哈希值的方法,例如Hash#select
。 - Alex Wayne