Block/Proc with Include for Ruby - ruby

I'm trying to think of a way to do this as a proc. Essentially the only part of the code that is different is that on substring match their is a .include? instead of a check for equals.
def check_exact_match(lead_attribute, tracker_attribute)
return true if tracker_attribute.nil?
return true if lead_attribute.downcase == tracker_attribute.downcase
false
end
def check_substring_match(lead_attribute, tracker_attribute)
return true if tracker_attribute.nil?
return true if lead_attribute.downcase.include? tracker_attribute.downcase
return false
end

I'm not sure if I remember how to code in Ruby elegantly, but what about something like this?
def check­_match(lea­d_attribut­e, track­er_attribu­te)­
track­er_attribu­te.nil? or yield lead_­attribute,­ track­er_attribu­te
end
The function can then be called like this:
check_match("abcd", "bd") { |l, t| l.downcase == t.downcase }
check_match(la, ta) { |l, t| l.downcase.include? t.downcase }

Modification from #busy_wait.
def check­_match(lea­d_attribur­e, track­er_attribu­te, &condition)­
track­er_attribu­te.nil? or condition.­call(lead_­attribute,­ track­er_attribu­te)
end
def check_exact_match(lead_attribute, tracker_attribute)
check_match(lea­d_attribur­e, track­er_attribu­te) { |l, t| l.downcase == t.downcase }
end
def check_substring_match(lead_attribute, tracker_attribute)
check_match(lea­d_attribur­e, track­er_attribu­te) { |l, t| l.downcase.include? t.downcase }
end

Related

How to recreate the any? method in Ruby

I am trying to recreate the enumerable module in Ruby. I am up to the any? method and having difficulty returning true or false. Instead each array item is returned 1 by 1.. Here is my code:
def my_any?
return self.to enum unless block_given?
self.each do |i|
return true if i == yield(i)
end
end
nums = [3,5,7,3,6,10,20,16]
puts nums.my_any?{|x|x==6}
Any ideas where I am going wrong?
You have three issues with your code: you should return an enumerator for this method when called without block, you should check just what yield returns, and you should explicitly return false on fail:
def my_any?
return to_enum(:my_any?) unless block_given?
each { |i| return true if yield(i) }
false
end
nums = [3,5,7,3,6,10,20,16]
puts nums.my_any? { |x| x == 6 }
#⇒ true
lazy = nums.my_any?
lazy.each { |x| x == 6 }
#⇒ true
Or, I would better use break:
def my_any?
return to_enum(:my_any?) unless block_given?
each { |i| break true if yield(i) } == true
end
You have two issues:
You're missing a return false if the loop fails to find a match. Currently when it fails to match, it'll give the return value from each, which is what you're seeing.
It's currently always failing, because while your return true if cond construct is right, any?'s conditional is not i == yield(i): you've got too many comparisons. You need just yield(i).
(The to enum bit sounds off too, but that's unrelated to your question.)
Slotting those changes into your code:
def my_any?
# FIXME: return self.to enum unless block_given?
self.each do |i|
return true if yield i
end
false
end

How to replace all nil value with "" in a ruby hash recursively?

str = "<a><b><c></c></b></a>"
hash = Hash.from_xml(str)
# => {"a"=>{"b"=>{"c"=>nil}}}
How can I replace all nils in a Hash to "" so that the hash becomes:
{"a"=>{"b"=>{"c"=>""}}}
Here is a recursive method that does not change the original hash.
Code
def denilize(h)
h.each_with_object({}) { |(k,v),g|
g[k] = (Hash === v) ? denilize(v) : v.nil? ? '' : v }
end
Examples
h = { "a"=>{ "b"=>{ "c"=>nil } } }
denilize(h) #=> { "a"=>{ "b"=>{ "c"=>"" } } }
h = { "a"=>{ "b"=>{ "c"=>nil , "d"=>3, "e"=>nil}, "f"=>nil } }
denilize(h) #=> { "a"=>{ "b"=>{ "c"=>"" , "d"=>3, "e"=>""}, "f"=>"" } }
this will destroy the original hash and will not work with hashes with infinite recursion.
def nil2empty(hash)
hash.keys.each do |key|
if hash[key].kind_of? Hash
nil2empty(hash[key])
else
hash[key] = '' if hash[key].nil?
end
end
true # of course, what else? :P
end
example of usage:
hash
=> {"a"=>{"b"=>{"c"=>nil}}}
nil2empty(hash)
=> true
hash
=> {"a"=>{"b"=>{"c"=>""}}}
I know this is not the answer you are expecting, but if you could handle a value instead of "" , this code works
eval({"a"=>{"b"=>{"c"=>nil}}}.to_s.gsub("nil", "1")) #=> returns a hash #{"a"=>{"b"=>{"c"=>1}}}

How do I use regular expressions in Ruby?

I don't know how to implement regular expressions in Ruby. I tried this code, but it always returns true:
firstName = "Stepen123"
res = Validation_firstName(firstName)
puts res
def Validation_firstName(firstName)
reg = /[a-zA-z][^0-9]/
if reg.match(firstName)
return true
else
return false
end
end
I am not sure what I did wrong.
You can rewrite your method like this:
def validation_firstname(first_name)
!!first_name[/^[a-z]+$/i]
end
def validation_firstname(first_name)
first_name.scan(/\d+/).empty?
end
p validation_firstname("Stepen123") #=> false
p validation_firstname("Stepen") #=> true

implementation issue of a rspec test in ruby

i have this test in ruby I'm trying to implement
require "silly_blocks"
describe "some silly block functions" do
describe "reverser" do
it "reverses the string returned by the default block" do
result = reverser do
"hello"
end
result.should == "olleh"
end
it "reverses each word in the string returned by the default block" do
result = reverser do
"hello dolly"
end
result.should == "olleh yllod"
end
end
here's the method
def do_reverse(str)
str = str.split
first_str = str[0].reverse
second_str= str[1]
if (second_str == nil)
str = first_str.to_s
else
second_str = str[1].reverse
str = (first_str +" "+ second_str)
end
end
what is the best way that i could implement it . when i try to rake the test it failed , but the method by itself return the reserve. i'm just a little confused.
Try this code:
def reverser
yield.split.map { |word| word.reverse}.join(" ")
end
Here's an easy way of doing what you're looking for, with specs.
# lib/reverse_words.rb
def reverse_words(phrase)
return '' if phrase.nil?
words = phrase.split
phrase.split.map(&:reverse!).join(' ')
end
def reverser
reverse_words(yield)
end
# spec/reverse_words_spec.rb
describe "#reverse_words" do
context "when single word" do
subject { reverse_words("hello") }
it { should == "olleh" }
end
context "when multiple words" do
subject { reverse_words("hello dolly") }
it { should == "olleh yllod" }
end
context "when nil" do
subject { reverse_words(nil) }
it { should == '' }
end
context "when empty" do
subject { reverse_words('') }
it { should == '' }
end
end
Note that the reverser spec simply makes use of the behavior that reverse_words has already been specced to pass.
describe "#reverser" do
subject do
reverser do
"this is a test"
end
end
it { should == reverse_words("this is a test") }
end
Here's a less wordy reverse_words spec:
describe "#reverse_words (less wordy)" do
# counterintuitive keys as answers to support the nil case
cases = { "olleh" => "hello",
"olleh yllod" => "hello dolly",
'' => nil,
'' => ''
}
cases.each_pair do |expected, input|
context "#{input} should equal #{expected}" do
subject { reverse_words(input) }
it { should == expected }
end
end
end
This works. The data you want is stored in "yield".
def reverser
yield.gsub(/\w+/) { |w| w.each_char.to_a.reverse.join }
end
My reverser method:
def reverser
# yield is the string given in the block
words = yield.split(' ')
final = []
words.each do |word|
final.push(word.reverse)
end
final.join(' ')
end
So. I came here looking for information on how to do this also. As the language wasn't clear. I went and looked offsite, and found enough information to pass the tests.
So, blocks are those things between curly braces that sometimes follow functions in ruby, such as
list.each {|i| i.reverse}
So what the spec is doing is trying to figure out what happens when it does:
rerverser {"hello"}
Putting yield in a function just returns whatever is in the block, so
def print_block
puts yield
end
print_block {"Hello world."}
#=> "Hello world"
Then you can just manipulate yield like you would manipulate any argument. There's a lot more to blocks. Here's a good place to start, but that's all you need to know to solve the exercise if you've solved all of Test First's learn_ruby exercises up until now.

Generate a different range in Ruby i.e. all possible /[0-9A-Za-z]{3}/

I feel like I'm using Ruby the wrong way here: I want to generate all possible matches for the regular expression /[0-9A-Za-z]{3}/
I can't use succ because "999".succ => "1000" and "zZz".succ => "aaAa".
I'm having trouble using ranges because I can't seem to union (0..9), ('A'..'Z'), ('a'..'z')
So I wrote:
def alphaNumeric
#range and succ don't cut it for [0-9a-zA-Z]
(0..9).each{|x|yield x.to_s}
('a'..'z').each{|x|yield x}
('A'..'Z').each{|x|yield x}
end
def alphaNumericX3
alphaNumeric{ |a|
alphaNumeric{ |b|
alphaNumeric{ |c|
yield a+b+c
}
}
}
end
alphaNumericX3.each{|x|p x}
My question is 2 fold:
Is there a less ugly way, and is there a way where alphaNumericX3 could be defined from the parameters (alphaNumeric, 3)?
PS I'm aware that I could define a new class for range. But thats definitly not shorter. If you can make this next block shorter and clearer than the above block, please do:
class AlphaNum
include Comparable
attr :length
def initialize(s)
#a=s.chars.to_a
#length=#a.length
end
def to_s
#a.to_s
end
def <=>(other)
#a.to_s <=> other.to_s
end
def succ
def inc(x,n)
return AlphaNum.new('0'*(#length+1)) if x<0
case n[x]
when '9'
n[x]='A'
when 'Z'
n[x]='a'
when 'z'
n[x]='0'
return inc(x-1,n)
else
n[x]=n[x].succ
end
return AlphaNum.new(n.to_s)
end
inc(#length-1,#a.clone)
end
end
# (AlphaNum.new('000')..AlphaNum.new('zzz')).each{|x|p x}
# === alphaNumericX3.each{|x|p x}
Use Array#product:
alpha_numerics = ('0'..'9').to_a + ('a'..'z').to_a + ('A'..'Z').to_a
alpha_numerics
.product(alpha_numerics, alpha_numerics)
.map { |triplet| triplet.join('') }
class String
def nextify
case self
when '9' then 'A'
when 'Z' then 'a'
when 'z' then '0'
else self.succ
end
end
end
class AlphaNum
def initialize(string)
#string = string
end
def succ
#string.split(//).inject("") { |s,n| s << n.nextify }
end
def method_missing(*args, &block)
#string.send(*args, &block)
end
end
a = AlphaNum.new("999")
puts a.succ #=> 'AAA'

Resources