这个问题适用于非常具体的案例,我可以更改params。这不是任何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"}
无论如何将上面两行合并成一个?
答案 0 :(得分:4)
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"}
答案 1 :(得分:1)
params.each{|_, v| v.strip! if v}.reject!{|_, v| !v || v.length == 0}
答案 2 :(得分: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? }
答案 3 :(得分:0)
这是一个似乎在技术上回答你的问题的选项,但我猜它不是你想要的:
params.select{|_,v| v.strip.length > 0 if v}
你遇到的根本问题是Hash #map确实不返回一个哈希而是一个数组。许多人,包括我自己,都觉得这很烦人。例如,请参阅:http://www.ruby-forum.com/topic/185611
这是一个使用inject的详细选项。
params.inject({}) {|h,(k,v)| h.merge(k => v ? v.strip : v)}.select{|_,v| v.length > 0 if v}
如果对您很重要,这些解决方案都不会对params进行任何破坏性更改。
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}
注入是一个棘手的功能,需要一些人习惯。我将尝试逐步解释这一行:
params.inject({}}
表示要创建一个空哈希来存储我们的结果。接下来它变得有点毛茸茸。我将从内到外解压缩下一个命令。
v ? v.strip : v
使用三元运算符返回v.strip,如果v计算结果为true,则v为v或false
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语句是直截了当的。我使用select而不是keep_if,因为尽管没有!,keep_if是一种破坏性的方法。看到这个咆哮:http://news.ycombinator.com/item?id=2247352。由于我们的inject语句返回一个哈希值,我们可以直接在其上调用.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"}
答案 4 :(得分:0)
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?}