2012-11-13 113 views
4

这个问题是非常非常具体的情况下,我可能会改变params。这不是任何Rails应用程序的一部分。ruby​​合并两个语句到一个

params为{:email => " ab", :xyz => " ", :opq => nil} 我运行以下:

params.each{|_, v| v.strip! if v} 
params.keep_if{|_, v| v.length > 0 if v} 

得到PARAMS作为 {:email => "ab"}

反正是有合并上述两行成一个?

+3

我会认为这是坏的形式发生变异的'params'对象轨道。改用一个返回新散列的方法。就像说'哈希#选择'一样。 –

+0

是的,删除换行并插入一个点;-)'params.each {| _,v | v.strip!如果v} .keep_if {| _,v | v.length> 0如果v}' – tokland

回答

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

使用'strip!'来匹配提问者的期望值。 –

+0

是不是使这个优雅的复杂性,他想要选择特定的元素*和*在一个语句中转换它们(条)? – spike

+0

@Dave它不会改变参数。我必须接受中间变量的帮助。 'ab = params.select {| _,v | v && v.strip.length> 0}'然后是'params = ab'这样仍然有两行 – JVK

1
params.each{|_, v| v.strip! if v}.reject!{|_, v| !v || v.length == 0} 
+1

除非有很好的需求,否则我会避免使用副作用函数:在这种情况下,我不能辩论存在(但可以在这里争辩不是)。 – 2012-11-13 21:37:20

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#mashObject#present?援助它的那样简单:

params2 = params.mash { |k, v| [k, v.strip] if v.present? } 
0

这里,似乎在技术上回答你的问题一个选项,但我猜测它是不是你在找什么:

params.select{|_,v| v.strip.length > 0 if v} 

你遇到的根本麻烦是,哈希#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} 

注入是一个棘手的功能,需要一些习惯。我会尽力解释一步此行步:

  • params.inject({}}说,创建一个空的哈希存储在我们的结果
  • | H,(K,V)|表示将新的空散列传递给变量h,同时还将原始参数散列中的键值对分别传递给k,v。

接下来它得到了很多毛。我会从内到外解开下一个命令。

  • v ? v.strip : v使用三元运算符返回v。在v计算结果为true或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语句是直线前进。我使用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"} 
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?}