4

这个问题是针对非常具体的情况,我可能会更改参数。这不是任何 Rails 应用程序的一部分。

参数是{:email => " ab", :xyz => " ", :opq => nil} 我运行以下:

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

获取参数为 {:email => "ab"}

有没有将以上两行合并为一条?

4

5 回答 5

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"}
于 2012-11-13T21:37:13.803 回答
1
params.each{|_, v| v.strip! if v}.reject!{|_, v| !v || v.length == 0}
于 2012-11-13T21:33:01.180 回答
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? }
于 2012-11-13T21:53:59.923 回答
0

这是一个似乎在技术上回答您的问题的选项,但我猜这不是您想要的:

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({}}说要创建一个空哈希来存储我们的结果。
  • |h, (k,v)| 表示将新的空散列传递到变量 h 中,同时将原始参数散列中的键、值对分别传递给 k、v。

接下来它有点毛茸茸的。我将从里到外解开下一个命令。

  • 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"} 
于 2012-11-13T23:21:31.633 回答
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?}
于 2012-11-13T23:58:45.843 回答