Ruby combines two operators in one

This question relates to a very specific case where I can change the parameters. This is not part of any rails application.

params {:email => " ab", :xyz => " ", :opq => nil} I do the following:

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

to get parameters like {:email => "ab"}

anyway merges over two lines into one?

+4
source share
5 answers
 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"} 
+4
source
 params.each{|_, v| v.strip! if v}.reject!{|_, v| !v || v.length == 0} 
+1
source

Actually, the lines you wrote can be linked:

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

This works because each returns the object itself (which has been updated). However, IMHO on-site 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 too verbose because stdlib lacks some fundamental abstractions. Using Enumerable#mash and Object#present? it is simple as:

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

Here is one option that seems to technically answer your question, but I assume this is not what you are looking for:

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

The main problem that you are facing is that the Hash # card does not support a hash, but rather an array. Many people, including me, find this annoying. See for example: http://www.ruby-forum.com/topic/185611

Here is a detailed option using injection.

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

If this matters to you, none of these solutions will lead to any destructive parameter changes.

 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 complex function that gets used to. I will try to explain this line step by step:

  • params.inject({}} says to create an empty hash to store our results.
  • | h, (k, v) | says to pass a new empty hash to the variable h, and also pass a key, a pair of values ​​from our original hash params to k, v respectively.

Then it becomes more hairy. I will unpack the following command from the inside.

  • v ? v.strip : v v ? v.strip : v uses the ternary operator to return v.strip when v evaluates to true or v if v is false or nil

  • k => v ? v.strip : v k => v ? v.strip : v creates a new hash with the result

  • h.merge(k => v ? v.strip : v) merges our new hash into h, which started empty and then passes the result to the next iteration of the injection cycle.

  • in the next iteration of the loop, h will no longer be empty, and future results will continue to merge on it.

At this point, we shared the hash, and if we stayed here, the result would look 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 removed, the select statement is direct. I use select here, not keep_if, because despite the absence !, Keep_if is a destructive method. See This Brew: http://news.ycombinator.com/item?id=2247352 . Since our injection instruction returns a hash, we can call it .select directly on it, although I do not propose making your lines of code so long in real practice.

 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
source
 params.keys.each{|k| v = h.delete(k); h[k] = v.strip if v and !v.empty?} 

or

 params.select!{|k, v| v and v.strip!; v and !v.empty?} 
0
source

Source: https://habr.com/ru/post/1445869/


All Articles