Why does output of & operator with any logic operation doesn't give any output in Ruby? - ruby-on-rails

puts "Hello World"
scores = {"biology" => ['unit_test','final_exam'],
"maths" => ['quiz','class_participation','final_exam']
}
x = (scores["biology"] & %w[flying_test])
puts "result of x && scores[\"biology\"].any? => #{x && scores["biology"].any?}"# Why does this return true?
y = scores["maths"] & %w[quiz]
z = scores["maths"].any?
puts "result of scores[\"maths\"] & %w[quiz] => #{y}" # returns true
puts "result of scores[\"maths\"].any? => #{z}" # return true
puts "result of y && z => #{y && z}"
puts "******"
puts "Clubbing all conditions, returns no output, why? it is actually evluates to (true || true), right"
puts ( (scores["biology"].any? && (scores["biology"] & %w[flying_test])) ||
(scores["maths"].any? && (scores["maths"] & %w[quiz])) )
# But when above two sub-conditions are swapped puts print the value as true
puts "$$$$$$$"
puts ((scores["biology"] & %w[flying_test]) && scores["biology"].any?) ||
((scores["maths"] & %w[quiz]) && scores["maths"].any?)
puts "cross check"
# puts (1 == 1).any?
https://onlinegdb.com/YBmzutZOj - you can execute here

what are you actually trying to do with your "&"?
simplifying examples:
puts ( scores["biology"] & %w[flying_test] )
are you trying to check that the object exists, and only return the object, ala:
if scores["biology"].include?('flying_test')
or are you trying to do an addition:
scores["biology"] + %w[flying_test]
or return your list if there are no scores?
scores["biology"] || %w[flying_test]
...
or is it that you want to include the "&" as part of the test of what to return:
puts (scores['biology'].any? && scores['biology'].include?('flying_test') && %w[flying_test]) ||
(scores['maths'].any? && scores['maths'].include?('quiz') && %w[quiz])
or possibly, more like (closer to your style of coding):
puts (scores["biology"] & %w[flying_test]).any? && (scores["biology"] & %w[flying_test]) ||
scores["maths"] & %w[quiz]
?

&& returns the second operand, if both operands are truthy, and in ruby the empty list is truthy.
In your particular case, x = (scores["biology"] & %w[flying_test]) evaluates to the empty list [], so x && scores["biology"].any? actually evaluates to [] && true, so true.
Also, in
puts ( (scores["biology"].any? && (scores["biology"] & %w[flying_test])) ||
(scores["maths"].any? && (scores["maths"] & %w[quiz])) )
the first operand also evaluates to an empty list, so the entire || operation evaluates to the empty list []. Doing a puts [] results in a no output being generated.

Related

search for matching key-value pair in an array of hashes and return true if match found

Suppose I have this array of hashes:
[ {"nutrient"=>"protein", "value"=>12, "calories"=>48, "unit"=>"g"},
{"nutrient"=>"fat", "value"=>5, "calories"=>45, "unit"=>"g"},
{"nutrient"=>"fibre", "value"=>1, "calories"=>nil, "unit"=>"g"},
{"nutrient"=>"carbohydrates", "value"=>67, "calories"=>268, "unit"=>"g"},
{"nutrient"=>"calcium", "value"=>42, "calories"=>nil, "unit"=>"mg"}]
How can I return boolean true if (nutrient value is equal to 'carbohydrates' and it's calories are equal to 268 ) and (if nutrient value is equal to 'protein' and it's calories are equal to 48)
That is, in short I want to return true for above array of hash.
a.count do |hash|
(hash['nutrient'] == 'carbohydrates' && hash['calories'] == 268) || (hash['nutrient'] == 'protein' && hash['calories'] == 48)
end == 2
What this does, is it counts any element in the collection, that passes EITHER this condition:
hash['nutrient'] == 'carbohydrates' && hash['calories'] == 268
OR this one
hash['nutrient'] == 'protein' && hash['calories'] == 48
And it returns true if there are exactly two matches.
Assuming that the nutrient values are unique, you could build a calories hash via:
calories = a.each_with_object({}) { |e, h| h[e['nutrient']] = e['calories'] }
#=> {"protein"=>48, "fat"=>45, "fibre"=>nil, "carbohydrates"=>268, "calcium"=>nil}
And check for the values via:
calories['carbohydrates'] == 268 && calories['protein'] == 48
#=> true
Perhaps this:
a.any? {|h| h['nutrient'] == 'carbohydrates' && h['calories'] == 268} &&
a.any? {|h| h['nutrient'] == 'proteins' && h['calories'] == 48}
# => true
Or as a nice finder method:
a = [ {"nutrient"=>"protein", "value"=>12, "calories"=>48, "unit"=>"g"}, {"nutrient"=>"fat", "value"=>5, "calories"=>45, "unit"=>"g"}, {"nutrient"=>"fibre", "value"=>1, "calories"=>nil, "unit"=>"g"}, {"nutrient"=>"carbohydrates", "value"=>67, "calories"=>268, "unit"=>"g"}, {"nutrient"=>"calcium", "value"=>42, "calories"=>nil, "unit"=>"mg"}]
def all?(array, *finders)
finders.all? do |finder|
array.any? { |hash| finder.all? { |k,v| hash[k] == v } }
end
end
puts all?(
a,
{'nutrient' => 'protein', 'value' => 12},
{'nutrient' => 'fat', 'calories' => 45}
).inspect
puts all?(
a,
{'nutrient' => 'protein', 'value' => 12},
{'nutrient' => 'fat', 'calories' => 46}
).inspect
Outputs:
true
false
The method will return false if a matching hash is not found from any of the hashes inside the array.
Below, arr is the given array of hashes (as in the example) and target is a second array of hashes such as the following.
target = [{ "nutrient"=>"carbohydrates", "calories"=>268 },
{ "nutrient"=>"protein", "calories"=>48 }]
We wish to determine if, for all hashes h in target, there is a hash in arr having the same key-value pairs as those that comprise h. We can do that with the following method.
Code
def all_match?(arr, target)
target.all? { |h| arr.any? { |g| g.merge(h) == g } }
end
Examples
For the above value of target, we obtain
all_match?(arr, target)
#=> true
Now let's modify target so there is no match in arr.
target[1]["calories"] = 50
#=> 50
target
#=> [{"nutrient"=>"carbohydrates", "calories"=>268},
# {"nutrient"=>"protein", "calories"=>50}]
all_match?(arr, target)
#=> false
Explanation
In the second example the steps are as follows. The first element of target is passed to the block, resulting in
h = target[0]
#=> {"nutrient"=>"carbohydrates", "calories"=>268}
and the block calculation is performed.
arr.any? { |g| g.merge(h) == g }
#=> true
As it happens, the matching hash is
g = arr[3]
#=>{"nutrient"=>"carbohydrates", "value"=>67, "calories"=>268, "unit"=>"g"},
g.merge(h) == g
#=> true
What I've done is merge h into each hash in arr until/if one is found, g, that returns g unchanged by the merge. For that to happen all key-value pairs in h must be present in g.
Because true was returned, all? passes the second element of target to the block and the block calculation is performed.
h = target[1]
#=> {"nutrient"=>"protein", "calories"=>50}
arr.any? { |g| g.merge(h) == g }
#=> false
Having found a false, all? returns false.
a=[ {"nutrient"=>"protein", "value"=>12, "calories"=>48, "unit"=>"g"}, {"nutrient"=>"fat", "value"=>5, "calories"=>45, "unit"=>"g"}, {"nutrient"=>"fibre", "value"=>1, "calories"=>nil, "unit"=>"g"}, {"nutrient"=>"carbohydrates", "value"=>67, "calories"=>268, "unit"=>"g"}, {"nutrient"=>"calcium", "value"=>42, "calories"=>nil, "unit"=>"mg"}]
a.map! do |value|
if value["nutrient"].eql?'protein' and value["calories"].eql?268
true
elsif value["nutrient"].eql?'protein' and value["calories"].eql?48
true
else
false
end
end
puts a.inspect

How to use multiple #select blocks in Ruby?

Let's say I have a list of records like:
transactions = Transaction.all
And I have the following instance methods #currency, #geo, #industry. I want to select records which has the following criteria:
Select all transactions that has field currency which equals to #currency unless #currency is nil and in this case we'll ignore the condition (currency would mean all currencies when it's nil)
Select all transactions that has field geo which equals to #geo unless #geo is nil.
Select all transactions that has field industry which equals to #industry unless #industry is nil.
I tried multiple #select but with no luck something like:
transactions.select{ |i| (i.currency == #currency) unless #currency.nil? }.
.select{ |i| (i.geo == #geo) unless #geo.nil? }.
.select{ |i| (i.industry == #industry) unless #industry.nil? }
The problem with your example is the unless #currency.nil? will return nil (which is falsey) if #currency is nil, which is the opposite of what you intended.
You should use || instead:
transactions.select{ |i| (i.currency == #currency) || #currency.nil? }.
select{ |i| (i.geo == #geo) || #geo.nil? }.
select{ |i| (i.industry == #industry) || #industry.nil? }
In this case, if #currency is nil, the first condition will return true, and all elements will pass the select box to the next one...
Another option would be to run the select block only is the parameter is not nil. In this case, you'd like to break the line into separate blocks:
transactions.select!{ |i| (i.currency == #currency) } unless #currency.nil?
transactions.select!{ |i| (i.geo == #geo) } unless #geo.nil?
transactions.select!{ |i| (i.industry == #industry) } unless #industry.nil?
transactions.select do |t|
(#currency.nil? || t.currency == #currency) &&
(#geo.nil? || t.geo == #geo) &&
(#industry.nil? || t.industry == #industry)
end
this should do the job.
Or, if you are into dynamics:
[:currency, :geo, :industry].all? do |field|
(ivar = instance_variable_get("##{field}")).nil? || t.send(field) == ivar
end
Use AR/SQL instead of Ruby processing when possible:
transactions.where(currency: #currency, geo: #geo, industry: #industry)
Multiple use of select is superfluous in this situation. You can use && and || logical operators:
transactions.select do |transaction|
(#currency.nil? || transaction.currency == #currency) &&
(#geo.nil? || transaction.geo == #geo) &&
(#industry.nil? || transaction.industry == #industry)
end

Converting base-10 to base2 in Ruby using recursion (Binary converter)

I would like to convert a base10 number to base2 in Ruby without using the built in to_s(2) method, using recursion.
I wrote this:
def to_binary(d)
if d<1
return ""
else
return to_binary(d/2).to_s + (d%2).to_s
end
end
This would return all correct results EXCEPT 0. Is there any way to return 0 for 0 without having leading zeroes for numbers greater than 0?
You can modify your checks a bit:
def to_binary(d)
return d.to_s if [0,1].include?(d) # same as "if d == 0 || d == 1"
to_binary(d/2) + (d%2).to_s
end
to_binary(10) == "1010"
#=> true
to_binary(0) == "0"
#=> true
You could also write above method as:
def to_binary(d)
return d.to_s if [0,1].include?(d)
div,mod = d.divmod(2)
to_binary(div) + mod.to_s
end

Inspect in Ruby

When I use this code:
x = []
x << 1
if (x[0].inspect == 1)
puts "OLLAAA"
end
It outputs nothing, but it should because x[0].inspect is == to 1. But if I change == to != I get output "OLLAAA", or when if is changed to unless. Any ideas?
Fixnum#inspect is an alias for to_s - you need to compare against "1"
Why are you so sure x[0].inspect == 1? Object::inspect returns a string.
$ irb
2.0.0-p247 :001 > x = []
=> []
2.0.0-p247 :002 > x << 1
=> [1]
2.0.0-p247 :003 > x[0].inspect == 1
=> false
If you change == to !=, obviously you flip the logic, so it prints. The exact same thing is happening for if to unless.
Because of below :
x[0].inspect # => "1"
x[0].inspect gives string instance,which is not equal to Fixnum instance 1. Thus x[0].inspect == 1 evaluates to false,and you didn't get the output. Now when you use !=,hope you got the point why you did get the output.
Fixnum#inpect call actually does Fixnum#to_s. See below :
12.method(:inspect) # => #<Method: Fixnum#to_s>
as mentioned above, inspect return a string. You can solve your problem with
if (x[0].inspect.to_i == 1)
puts "Hey I am an integer :)"
end

asp.net mvc datettime linq check for empty

var postsidebar = from post in postrepository.GetAllPosts()
join pstmt in postrepository.GetAllPostMetas()
on post.int_PostId equals pstmt.int_PostId
where (post.int_PostTypeId == 4
&& post.int_PostStatusId == 2
&& post.int_OrganizationId == layoutrep.GetSidebarDetailById(SidebarDetailsId).int_OrganizationId)
&& (pstmt.vcr_MetaKey.Contains(filter) && pstmt.vcr_MetaValue.Contains("true")
&& (System.DateTime.Now >=
Convert.ToDateTime(pstmt.Post.PostMetas.FirstOrDefault(m =>
m.vcr_MetaKey == "Publish Date").vcr_MetaValue)))
select post;
how can i check for empty in this part in Date(it is giving error)
&& (System.DateTime.Now >= Convert.ToDateTime(pstmt.Post.PostMetas.FirstOrDefault(m =>
m.vcr_MetaKey == "Publish Date").vcr_MetaValue)))
You could try eliminated the possibility of an empty value first and then try your cast afterward.
&& pstmt.Post.PostMetas.FirstOrDefault(m =>
m.vcr_MetaKey == "Publish Date"
&& !string.IsNullOrEmpty(m.vcr_MetaValue))
&& (System.DateTime.Now >=
Convert.ToDateTime(pstmt.Post.PostMetas.FirstOrDefault(m =>
m.vcr_MetaKey == "Publish Date").vcr_MetaValue)))
Try this:
// declare the action for re-use
Func<PostMeta,bool> action = m => m.vcr_MetaKey == "Publish Date";
// then test for Any() before comparing anything
&& (pstmt.Post.PostMetas.Any(action) && System.DateTime.Now >= Convert.ToDateTime(pstmt.Post.PostMetas.First(action).vcr_MetaValue)))

Resources