Double Ampersand Input

I have an injection call

[2,4,6].inject(true) { |res, val| res && val % 2 == 0 } 

and you want to send the && operator for input, as in inject(0, :+) . How can i do this?

+7
ruby
source share
4 answers

You cannot, because && and || , unlike other operators, are not syntactic sugar for methods (i.e. there is no method called && or || ), so you cannot refer to them using a symbol.

However, you can avoid using inject to compute a logical conjunction or disjunction of an array of booleans by replacing it with all? or any? accordingly, because for any array the following conditions are true:

 ary.inject(true) { |res, b| res && b } == ary.all? ary.inject(false) { |res, b| res || b } == ary.any? 

So, for example, the code you posted can be rewritten as:

 [2,4,6].map(&:even?).all? # => true 

Update : it is obvious that my last example is the wrong way to express this calculation, falsetru's answer is much faster:

 require 'fruity' compare( -> { (0..1000).map(&:even?).all? }, -> { (0..1000).all?(&:even?) } ) 
 Running each test 1024 times. Test will take about 2 seconds. Code 2 is faster than Code 1 by 111x ยฑ 10.0 
+10
source share

How about using Enumerable#all?

 [2,4,6].all? &:even? # => true [2,4,6,5].all? &:even? # => false 

If you want to use inject , you need to define an instance method.

 class Object def is_even(val) self && val % 2 == 0 end end [2,4,6].inject(true, :is_even) # => true [1,2,4,6,5].inject(true, :is_even) # => false 
+8
source share

'& &' is not a method, so you cannot enter it. However, you can enter and use the method.

 [2,4,6,5].map(&:even?).inject(true, :&) 

What will the same do

NOTE. However, this should not be done, since it is extremely risky and can cause unexpected consequences (if you run in a collection containing at least one non-Boolean (true, false, nil) value). You should always use any? methods any? or all? .

+3
source share

inject(0, :+) will add all elements of the array, regardless of whether the contents of the elements (odd, even, etc.).

If you want to inject(true, &:&&) (I know this will not work), your array must be an array of booleans for your question in order to make sense that will be the same as: [true, false].all?

important: you cannot pass both the arg block and the actual block, which means you cannot check whether it even enters && at the same time.

If you insist, try this:

 [2,4,6].inject(true, & lambda { |x,y| x && y }) => 6 

This is the equivalent of what you are asking for (which I still don't understand)

0
source share

All Articles