Comparing the length of two strings with Ruby - ruby

Define a method called first_longer_than_second with a parameter called first and another called second. The method will return true if the first word passed in is greater than or equal to the length of the second word. It returns false otherwise. Here's how the method would be called and the expected return:
This is what I have:
def first_longer_than_second(first, second)
if first.length >= second.length
puts true
else
puts false
end
end
I am getting errors and I not sure why.

Ruby comparison operators like >= return boolean values naturally. You don't need to use a conditional, and you almost never want to return string equivalents of true and false. Also, Ruby convention is to use a question mark in the name of methods that return boolean values.
For this kind of method, Ruby lets us write this:
def first_longer_than_second?(first, second)
first.length >= second.length
end
Then you can call the method like this:
>> first_longer_than_second?('hello', 'sir')
=> true
Note that the method name is somewhat confusing since it returns true if first is the same length as second. You might consider renaming the method as appropriate. Names do matter!

Related

What is the difference between each and any to find a prime number in Ruby

There are two completely identical methods, only one uses each and the other any, so what is the difference between each and any?
first program code (each using):
def is_prime?(num)
Math.sqrt(num).floor.downto(2).each {|i| return false if num % i == 0}
true
end
number = gets.chomp.to_i;
puts is_prime?(number);
second program code (any using):
def is_prime?(num)
Math.sqrt(num).floor.downto(2).any? {|i| return false if num % i == 0}
true
end
number = gets.chomp.to_i;
puts is_prime?(number);
The .each method iterates through all elements of a data structure, most commonly an array or a hash, and calls the given block once for each element. If no block is given, it returns an enumerator, i.e. an instance of the Enumerator class that can then be used to "manually" iterate through the data structure.
The .any? method tests every element of a data structure against the given condition and returns true if one or more of them match or pass the test. Otherwise, it returns false. There are more details to it, so please check it from the official documentation.
General tips using Ruby
Based on this code, there are a couple of suggestions. First, you should not use return in a block as it makes the method return that value, too, and might not execute the block for more iterations.
Second, you don't need trailing semicolons at the ends of lines.
Short analysis of your code
Both your functions seem to work, at least for some numbers, but it seems that you might not exactly know why. Let's take a closer look at it.
Let's assume num = 5, for example.
First function, the block variable i gets assigned to a value of 2, meaning the block does not use the return false because the test num % i == 0 fails. Instead, the function returns true from the next line.
Second function, the block variable i also gets assigned to a value of 2, but again, as the test num % i == 0 fails the result of .any? is false, and the function returns true from the next line.
Now, let's assume num = 4.
First function, the block variable i gets again assigned to a value of 2, and since this time the test num % i == 0 passes, the return false inside the block is executed making the function return false.
Second function, the block variable i also gets again assigned to a value of 2, and since the test num % i == 0 passes here as well, the return false inside the block is executed making the function return false.
Without the return false in your second function, the function would always return true because you would not check the value returned by .any?, and the function's next line would be executed returning true.
Mechnicov offers simpler alternatives how to make your function more understandable.
each is the iterator that go through the array from beginning to end
Its main purpose is just to pass through the array (or other collection) and perform some actions that were specified in the block. For example, it can be a rendering of HTML partial or making HTTP requests or something else
There are also many other iterators that have specific tasks. These are such as map, select, any? and others
You used it wrong way. You're not using the full power of a specific iterator
But you can do it like this:
def prime?(num)
!Math.sqrt(num).floor.downto(2).any? { |i| num % i == 0 }
end
or like this
def prime?(num)
Math.sqrt(num).floor.downto(2).all? { |i| num % i != 0 }
end

Return boolean value based on string boolean input values

I have a paramter params[:input], and its value is coming as 'true' or 'false' (boolean values in string).
In database, the input values are stored as 1 and 0. I need to return boolean values based on input string values. I created a function below to return boolean values.
def status(input)
return unless input.present?
return false if ['false'].include?(input.downcase)
return true if ['true'].include?(input.downcase)
end
Not sure if this is the best way. Is there a better way to write this?
I would go with case. Since there is a binary state, you probably need to decide what value is to be chosen for a fallback. E. g. when no parameter is present, you are likely still in a need to return something. I would return false for everything save for 'true':
def status(input)
case input
when 'true' then true
when 'false' then false
else false
end
end
Or, even shorter (but less readable/idiomatic):
def status(input)
'true' == input
end
It seems like you want to cast a string to a boolean and you are using Ruby on Rails. Why don't you use the same method that Rails itself uses to translate user input into a boolean?
def status(input)
ActiveRecord::Type::Boolean.new.type_cast_from_user(value)
end
The name of the method changed in different versions of Rails. The above version is for Rails 4.2. Prior Rails 4.2 use ActiveRecord::ConnectionAdapters::Column.value_to_boolean(value) and since Rails 5 it is ActiveRecord::Type::Boolean.new.cast(value)
The advantage of using the build method it that it accepts not only the strings 'true' and 'false' but other common input and still returns a useful boolean.
The simplest solution, without overhead of switch statements, etc, is simply this:
def status(input)
input.is_a?(String) && input.casecmp?('true')
end
casecmp? ensures case-insensitivity, so 'true', 'TRUE', 'True', and any variation of different cases would all return a boolean true.
This could even be altered slightly more to simply ensure that input is a string by calling to_s on it, which will just return self if it is already a string.
def status(input)
input.to_s.casecmp?('true')
end
The first is a bit safer, as depending on the object passed, to_s could have been overridden and supply unpredictable behavior, though highly unlikely.
Another solution is using downcase and comparing with ==, but casecmp? is more optimized for comparison, and does not create an additional string as downcase would.
Documentation for case_cmp?

Simple way to understand returning from a block in ruby

My code is supposed to print integers in an array.
odds_n_ends = [:weezard, 42, "Trady Blix", 3, true, 19, 12.345]
ints = odds_n_ends.select { |x| if x.is_a?(Integer) then return x end }
puts ints
It gives me an error in the 2nd line - in 'block in <main>': unexpected return (LocalJumpError)
When I remove the return, the code works exactly as desired.
To find the mistake in my understanding of blocks, I read related posts post1 and post2. But, I am not able to figure out how exactly are methods and blocks being called and why my approach is incorrect.
Is there some call stack diagram explanation for this ? Any simple explanation ?
I am confused because I have only programmed in Java before.
You generally don't need to worry exactly what blocks are to use them.
In this situation, return will return from the outside scope, e.g. if these lines were in a method, then from that method. It's the same as if you put a return statement inside a loop in Java.
Additional tips:
select is used to create a copied array where only the elements satisfying the condition inside the block are selected:
only_ints = odds_n_ends.select { |x| x.is_a?(Integer) }
You're using it as a loop to "pass back" variables that are integers, in which case you'd do:
only_ints = []
odds_n_ends.each { |x| if x.is_a?(Integer) then only_ints << x end }
If you try to wrap your code in a method then it won't give you an error:
def some_method
odds_n_ends = [:weezard, 42, "Trady Blix", 3, true, 19, 12.345]
ints = odds_n_ends.select { |x| if x.is_a?(Integer) then return true end }
puts ints
end
puts some_method
This code output is true. But wait, where's puts ints??? Ruby didn't reach that. When you put return inside a Proc, then you're returning in the scope of the entire method. In your example, you didn't have any method in which you put your code, so after it encountered 'return', it didn't know where to 'jump to', where to continue to.
Array#select basically works this way: For each element of the array (represented with |x| in your code), it evaluates the block you've just put in and if the block evaluates to true, then that element will be included in the new array. Try removing 'return' from the second line and your code will work:
ints = odds_n_ends.select { |x| if x.is_a?(Integer) then true end }
However, this isn't the most Ruby-ish way, you don't have to tell Ruby to explicitly return true. Blocks (the code between the {} ) are just like methods, with the last expression being the return value of the method. So this will work just as well:
ints = odds_n_ends.select { |x| if x.is_a?(Integer) } # imagine the code between {} is
#a method, just without name like 'def is_a_integer?' with the value of the last expression
#being returned.
Btw, there's a more elegant way to solve your problem:
odds_n_ends = [:weezard, 42, "Trady Blix", 3, true, 19, 12.345]
ints = odds_n_ends.grep(Integer)
puts ints
See this link. It basically states:
Returns an array of every element in enum for which Pattern ===
element.
To understand Pattern === element, simply imagine that Pattern is a set (let's say a set of Integers). Element might or might not be an element of that set (an integer). How to find out? Use ===. If you type in Ruby:
puts Integer === 34
it will evalute to true. If you put:
puts Integer === 'hey'
it will evalute to false.
Hope this helped!
In ruby a method always returns it's last statement, so in generall you do not need to return unless you want to return prematurely.
In your case you do not need to return anything, as select will create a new array with just the elements that return true for the given block. As ruby automatically returns it's last statement using
{ |x| x.is_a?(Integer) }
would be sufficient. (Additionally you would want to return true and not x if you think about "return what select expects", but as ruby treats not nil as true it also works...)
Another thing that is important is to understand a key difference of procs (& blocks) and lambdas which is causing your problem:
Using return in a Proc will return the method the proc is used in.
Using return in a Lambdas will return it's value like a method.
Think of procs as code pieces you inject in a method and of lambdas as anonymous methods.
Good and easy to comprehend read: Understanding Ruby Blocks, Procs and Lambdas
When passing blocks to methods you should simply put the value you want to be returned as the last statement, which can also be in an if-else clause and ruby will use the last actually reached statement.

doubts regarding "||=" OR EQUALS operator in ruby [duplicate]

This question already has answers here:
What does ||= (or-equals) mean in Ruby?
(23 answers)
Closed 8 years ago.
I have some doubts regarding OR EQUALS (||=) operator in ruby. How does ruby interpreter implement it? Here is a sample of code:
class C
def arr
#num ||= []
end
end
When we use OR EQUALS operator in this circumstances, the first call to this method initializes the variable and adds an element, that's fine. When a second call is made to arr, how does it know that array has one element in it..
In Ruby, there are two values that are considered logical false. The first is the boolean value false, the other is nil. Anything which is non-nil and not explicitly false is true. The first time though the method, #num is nil, which is treated as false and the logical or portion of ||= needs to be evaluated and ends up assigning the empty array to #num. Since that's now non-nil, it equates to true. Since true || x is true no matter what x is, in future invocations Ruby short circuits the evaluation and doesn't do the assignment.
In general terms x ||= y is equivalent to x = x || y, it's just shorthand. It's implemented as the expanded form, same as &&=, += or -=.
Most programming languages, Ruby included, will stop executing a logical comparison statement like || on the first true value it encounters and return that. Likewise, it will halt on the first false value when using &&.
In general terms:
false || foo()
This will return false and not evaluate foo().
The pattern is best described as a "lazy initializer", that is the variable is defined only once, but only when it's actually used. This is in contrast to an "eager initializer" that will do it as early as possible, like inside the initialize method.
You'll see other versions of this pattern, like:
def arr
#num ||= begin
stuff = [ ]
# ...
stuff
end
end
This handles cases where the initial value is not as trivial and may need some work to produce. Once again, it's only actually generated when the method is called for the first time.
How does Ruby know on the second pass to not initialize it again? Simple, by that point #num is already defined as something.
As a note, if you're using values like false that would evaluate as non-true, then ||= will trigger every time. The only two logically false values in Ruby are nil and false, so most of the time this isn't an issue.
You'll have to do this the long-form way if you need to handle false as well:
def arr
return #num unless num.nil?
#num = false
end
There was talk of adding an ||=-like operator that would only trigger on nil but I don't think that has been added to Ruby yet.

Returning a value of ruby is strange

could anyone tell me the return value of this function give the parameter listed blew:
def sequence(*enumerables)
enumerables.each do |enumerable|
print "#{enumerable},"
end
end
a,b,c = [1,2,3],4..6,'a'..'e'
value = sequence(a,b,c)
print value
why the value is evaluated to be:
[[1,2,3],4..6,"a".."e"]
Remember that the last thing left on the stack is the return value of your method. This is always the case. If the return value is important, you must pay close attention to how you exit from your method.
The each method returns what it has been iterating over. Since the each is the last statement in your method, stack-wise, that value gets returned.
You can fix this by returning nothing:
def sequence(*enumerables)
enumerables.each do |enumerable|
print "#{enumerable},"
end
return
end
This approach is generally frowned on as the return method seems out of place. If the caller of this method is not expecting any particular return value, then it's not necessary.
The alternative is to return something useful:
def sequence(*enumerables)
enumerables.join(",")
end
puts sequence(a,b,c)
It's often the case that methods which do not set an expectation for a particular return value may return an arbitrary one.
enumerables is an array. The splat (*) operator causes this.
The return value of sequence is the return value of enumerables.each which is enumerables
A simple example:
def foo(*args)
args
end
foo(1,2,3,4) == [1,2,3,4] # true
You're returning enumerables, which is an array containing all the arguments to the method.
What did you expect value to contain? You haven't made any explicit attempt to return anything, so whatever value the last statement in the method resolves to "falls off" the method to become its return value.

Resources