[Ruby] Reduce

Post any examples or modules that you want to share here
Post Reply
tulamide
Posts: 2714
Joined: Sat Jun 21, 2014 2:48 pm
Location: Germany

[Ruby] Reduce

Post by tulamide »

I had to look at an array and get either true or false, depending on any value being greater than 1 or lower than -1.

After some time I came up with this:

Code: Select all

over = a.reduce(false) { |memo, n| n.abs >= 1 ? memo = true : memo }


I think it is the shortest form to get the desired result (but please post even shorter versions!), probably even in high execution speed.

'reduce' is a method of the array class that tries to reduce the array to one value, using a provided block. That block gets populated with a memo and the current value, and you can initialize memo (here: reduce(false) sets memo to false). If you don't, it will be initialized with the first value of the array - not good if you're looking for true or false.

The rest of the code checks if the absolute value is greater or equal 1 (digital clipping occured) and sets memo to true. If not, memo is passed back unaltered.

It would be an improvement if, with similar short code, one could break out of the loop on the first occurence of the condition. So, if you know a trick for that, please share :)
"There lies the dog buried" (German saying translated literally)
KG_is_back
Posts: 1196
Joined: Tue Oct 22, 2013 5:43 pm
Location: Slovakia

Re: [Ruby] Reduce

Post by KG_is_back »

If you are searching whether at least one value in array matches certain condition, just use .any? method. It also has the added benefit of terminating the iteration once it finds first match. Its inverse is the .all? method which terminates when it find first false.

Code: Select all

over = a.any? { |n| n.abs>=1 }


.any? method is a logical disjunction (logical OR of all values), it correctly returns false if the array is empty. Similarly .all? method returns true for empty array (vacuous truth).

Alternatively you may use .find or .find_index. They also terminate after they find matching element and return that element or nil if nothing was found respectively. It can be very useful when you need to both check if certain element exists and execute operation on it when it does:

Code: Select all

#turret will automatically attack enemy units in range 
if target=@units.find{|unit| unit.enemy_of?(self) and unit.in_range_of?(self)}
attack(target)
end
tulamide
Posts: 2714
Joined: Sat Jun 21, 2014 2:48 pm
Location: Germany

Re: [Ruby] Reduce

Post by tulamide »

Yes! .any? is what I was looking for. I was so focused on doing it with reduce that I ignored all the other fine methods. I think that's what is called mindcuffs. :lol:
"There lies the dog buried" (German saying translated literally)
RJHollins
Posts: 1573
Joined: Thu Mar 08, 2012 7:58 pm

Re: [Ruby] Reduce

Post by RJHollins »

great stuff Guys.

Understood that you're looking to get things done ... but to see ideas develop into
options/solutions and strategy if helpful to all of us [or just Me].

thx
8-)
KG_is_back
Posts: 1196
Joined: Tue Oct 22, 2013 5:43 pm
Location: Slovakia

Re: [Ruby] Reduce

Post by KG_is_back »

tulamide wrote:Yes! .any? is what I was looking for. I was so focused on doing it with reduce that I ignored all the other fine methods. I think that's what is called mindcuffs. :lol:


It's called writing in Ruby... just look at stack overflow. Topics for regular languages deal with "how do I make this work?" followed by responses with specific cryptic algorithms written in even more cryptic syntax. Topics for ruby start with "it works, but how do I make it look pretty?" followed by grammar nazis nitpicking each other's suggestions... :lol:

As for enumerables like arrays in ruby, half the methods are technically just modified versions of ".each" For example .any? is under the hood just this:

Code: Select all

def any?()
if block_given?
self.each{|v| return true if yield(v)}
return false
else
self.each{|v| return true if v}
return false
end
end
Post Reply