简体   繁体   English

ruby将两个语句合并为一个

[英]ruby merge two statements in to one

This question is for very very specific case, where I may change params. 这个问题适用于非常具体的案例,我可以更改params。 This is not a part of any rails app. 这不是任何rails应用程序的一部分。

params is {:email => " ab", :xyz => " ", :opq => nil} I run following : params是{:email => " ab", :xyz => " ", :opq => nil}我运行以下:

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

to get params as {:email => "ab"} 以# {:email => "ab"}获取参数

is there anyway to merge above two lines into one? 无论如何将两条线合并为一条线?

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}

Actually, the lines you wrote are chainable: 实际上,你写的行是可链接的:

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

This works because each returns the object itself (which was updated). 这是有效的,因为each返回对象本身(已更新)。 However, IMHO in-place updates are usually a bad idea, so here's a functional approach: 但是,恕我直言的就地更新通常是一个坏主意,所以这是一个功能方法:

params2 = Hash[params.map { |k, v| [k, v.strip] if v && v.strip.size > 0 }.compact]

But this is unnecessarily verbose because the stdlib lacks some fundamental abstractions. 但这是不必要的冗长,因为stdlib缺乏一些基本的抽象。 With the aid of Enumerable#mash and Object#present? Enumerable#mashObject#present?的帮助下Object#present? it's as simple as: 它很简单:

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

Here is one option that seems to technically answer your question, but I'm guessing it is not what you are looking for: 这是一个似乎在技术上回答你的问题的选项,但我猜它不是你想要的:

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

The fundamental trouble you are running into is that Hash#map does not return a Hash but rather an Array. 您遇到的根本问题是Hash #map 不会返回Hash而是返回Array。 Many people, including myself, find this annoying. 许多人,包括我自己,都觉得这很烦人。 See for example: http://www.ruby-forum.com/topic/185611 参见例如: http//www.ruby-forum.com/topic/185611

Here is a verbose option using inject. 这是一个使用inject的详细选项。

params.inject({}) {|h,(k,v)| h.merge(k => v ? v.strip : v)}.select{|_,v| v.length > 0 if v}

If it matters to you, neither of these solutions will make any destructive changes to params. 如果对您很重要,这些解决方案都不会对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} 

Inject is a tricky function that takes some getting used to. 注入是一个棘手的功能,需要一些人习惯。 I'll try to explain this line step by step: 我将尝试逐步解释这一行:

  • params.inject({}} says to create an empty hash to store our results in. params.inject({}}表示创建一个空哈希来存储我们的结果。
  • |h, (k,v)| | h,(k,v)| says to pass the new empty hash into the variable h while also passing the key, value pair from our original params hash into k, v respectively. 表示将新的空哈希值传递给变量h,同时还将原始参数哈希值中的键值对分别传递给k,v。

Next it get's kindof hairy. 接下来它变得有点毛茸茸。 I'll unpack the next command from the inside out. 我将从内到外解压缩下一个命令。

  • v ? v.strip : v v ? v.strip : v uses the ternary operator to return v.strip in the case that v evaluates to true or v in the case that v is false or nil v ? v.strip : v使用三元运算符在v计算结果为true时返回v.strip,如果v为false或为零则使用v

  • k => v ? v.strip : v k => v ? v.strip : v creates a new hash with the result k => v ? v.strip : v使用结果创建一个新哈希

  • h.merge(k => v ? v.strip : v) merges our new hash into h, which started out empty, and then passes the result onto the next iteration of the inject loop. h.merge(k => v ? v.strip : v)将我们的新哈希合并为h,它开始为空,然后将结果传递给注入循环的下一次迭代。

  • in the next iteration of the loop, h will no longer be empty and future results will continue to be merged onto it. 在循环的下一次迭代中,h将不再为空,并且将来的结果将继续合并到它上面。

At this point we have stripped the hash and if we stopped here the result looks like this: 此时我们已经删除了哈希,如果我们在这里停止,结果如下所示:

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} 

Now that the hash is stripped, the select statement is straight forward. 现在哈希被剥离,select语句是直截了当的。 I use select here rather than keep_if, because, despite the lack of a !, keep_if is a destructive method. 我使用select而不是keep_if,因为尽管没有!,keep_if是一种破坏性的方法。 See this rant: http://news.ycombinator.com/item?id=2247352 . 看到这个咆哮: http//news.ycombinator.com/item ?id = 22467352 Since our inject statement returns a hash we can directly call .select on it, although I don't suggest making your lines of code this long in actual practice. 由于我们的inject语句返回一个哈希,我们可以在它上面直接调用.select ,虽然我不建议在实际操作.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?}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM