I'm wondering, what would be the easiest way to check if all the elements of Array conform to certain criteria and return boolean? Is there maybe a pattern in Ruby to call method on collection and then return boolean value? Standard Enumerable methods return either Array or nil, so I'm not sure where to look.I've wrote an example that works using grep, but I feel that if could be skipped with more idiomatic code:
def all_matched_by_regex?(regex)
array_collection = ['test', 'test12', '12test']
matched = array_collection.grep(regex)
if matched.length == array_collection.length
return true
end
return false
end
Did you try Enumerable.all? {block} ? It seems like exactly what you're looking for.
Edit:
My Ruby is a bit rusty, but here's an example of how to use it
regex = /test/
=> /test/
array_collection = ['test', 'test12', '12test']
=> ["test", "test12", "12test"]
array_collection.all? {|obj| regex =~ obj}
=> true
You can change:
if matched.length == array_collection.length
return true
end
return false
with simply returning:
matched.length == array_collection.length
Like this:
def all_matched_by_regex?(regex)
array_collection = ['test', 'test12', '12test']
matched = array_collection.grep(regex)
matched.length == array_collection.length
end
Related
I have some ruby code that gets a json from Jenkins that contains an array of n items. The item I want has a key called "lastBuiltRevision"
I know I can loop through the array like so
actions.each do |action|
if action["lastBuiltRevision"]
lastSuccessfulRev = action["lastBuiltRevision"]["SHA1"]
break
end
end
but that feels very clunky and devoid of the magic that I usually feel when working with ruby.
I have only been tinkering with it for roughly a week now, and I feel that I may be missing something to make this easier/faster.
Is there such a thing? or is manual iteration all I can do?
I am kind of hoping for something like
lastSuccessfulRev = action.match("lastBuildRevision/SHA1")
Using Enumerable#find:
actions = [
{'dummy' => true },
{'dummy' => true },
{'dummy' => true },
{'lastBuiltRevision' => { "SHA1" => "123abc" }},
{'dummy' => true },
]
actions.find { |h|
h.has_key? 'lastBuiltRevision'
}['lastBuiltRevision']['SHA1']
# => "123abc"
UPDATE
Above code will throw NoMethodError if there's no matched item. Use follow code if you don't want get an exception.
rev = actions.find { |h| h.has_key? 'lastBuiltRevision' }
rev = rev['lastBuiltRevision']['SHA1'] if rev
Here's another way to do it, making use of the form of Enumerable#find that takes a parameter ifnone which is called, and its return value returned, if find's block never evaluates true.
I assume the method is to return nil if either key is not found.
Code
def look_for(actions, k1, k2)
actions.find(->{{k1=>{}}}) { |e| e.key?(k1) }[k1][k2]
end
Examples
actions = [{ 'dog'=>'woof' }, { 'lastBuiltRevision'=>{ 'SHA1'=> 2 } }]
look_for(actions, 'lastBuiltRevision', 'SHA1') #=> 2
look_for(actions, 'cat, 'SHA1') #=> nil
look_for(actions, 'lastBuiltRevision', 'cat') #=> nil
Explanation
I've made find's ifnone parameter the lambda:
l = ->{{k1=>{}}}
so that:
k1 = "cats"
h = l.call #=> {"cats"=>{}}
h[k1]['SHA1'] #=> {}['SHA1']
#=> nil
Try:
action.map { |a| a["lastBuiltRevision"] }.compact.map { |lb| lb["SHA1"] }.first
Is there a more readable way to test if delivery_status is one of three strings?
if ["partial", "successful", "unsuccessful"].include? delivery_status
Here's what I'd really like, but it doesn't work:
if delivery_status == ("partial" or "successful" or "unsuccessful")
While I would not advise this, you can do it anyway:
def String
def is_one_of?(array)
array.include?(self)
end
end
And then:
if delivery_status.is_one_of?([...])
But there is a much better solution: use case (if possible in your situation):
case delivery_status
when 'partial', 'successful', 'unsuccessful'
#stuff happens here
when ... #other conditions
end
if %w[partial successful unsuccessful].include? delivery_status
It's not intuitive, but using the Regexp engine can speed these tests up:
STATES = ["partial", "successful", "unsuccessful"]
regex = /\b(?:#{ Regexp.union(STATES).source })\b/i
=> /\b(?:partial|successful|unsuccessful)\b/i
delivery_status = 'this is partial'
!!delivery_status[regex]
=> true
delivery_status = 'that was successful'
!!delivery_status[regex]
=> true
delivery_status = 'Yoda says, "unsuccessful that was not."'
!!delivery_status[regex]
=> true
delivery_status = 'foo bar'
!!delivery_status[regex]
=> false
If I'm not searching a string for the word, I'll use a hash for a lookup:
STATES = %w[partial successful unsuccessful].each_with_object({}) { |s, h| h[s] = true }
=> {"partial"=>true, "successful"=>true, "unsuccessful"=>true}
STATES['partial']
=> true
STATES['foo']
=> nil
Or use:
!!STATES['foo']
=> false
If you want a value besides true/nil/false:
STATES = %w[partial successful unsuccessful].each_with_index.with_object({}) { |(s, i), h| h[s] = i }
=> {"partial"=>0, "successful"=>1, "unsuccessful"=>2}
That'll give you 0, 1, 2 or nil.
I ended up doing something similar to #Linuxios's suggestion
class String
def is_one_of(*these)
these.include? self
end
def is_not_one_of(*these)
these.include? self ? false : true
end
end
This allows me to write:
if delivery_status.is_one_of "partial", "successful", "unsuccessful"
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
I have seen and used by myself lots of ||= in Ruby code, but I have almost never seen or used &&= in practical application. Is there a use case for &&=?
Not to be glib, but the obvious use case is any time you would say x && foo and desire the result stored back into x. Here's one:
list = [[:foo,1],[:bar,2]]
result = list.find{ |e| e.first == term }
result &&= result.last # nil or the value part of the found tuple
any sort of iteration where you want to ensure that the evaluation of a boolean condition on all elements returns true for all the elements.
e.g.
result = true
array.each do |elem|
# ...
result &&= condition(elem) # boolean condition based on element value
end
# result is true only if all elements return true for the given condition
Validation of the document such as,
a = {'a' => ['string',123]}
where the element in a['a'] should be a String. To validate them, I think you can use,
def validate(doc, type)
valid = true
doc.each{|x|
valid &&= x.is_a? type
}
valid
end
1.9.3p392 :010 > validate(a['a'],String) => false
There is an array with 2 elements
test = ["i am a boy", "i am a girl"]
I want to test if a string is found inside the array elements, say:
test.include("boy") ==> true
test.include("frog") ==> false
Can i do it like that?
Using Regex.
test = ["i am a boy" , "i am a girl"]
test.find { |e| /boy/ =~ e } #=> "i am a boy"
test.find { |e| /frog/ =~ e } #=> nil
Well you can grep (regex) like this:
test.grep /boy/
or even better
test.grep(/boy/).any?
Also you can do
test = ["i am a boy" , "i am a girl"]
msg = 'boy'
test.select{|x| x.match(msg) }.length > 0
=> true
msg = 'frog'
test.select{|x| x.match(msg) }.length > 0
=> false
I took Peters snippet and modified it a bit to match on the string instead of the array value
ary = ["Home:Products:Glass", "Home:Products:Crystal"]
string = "Home:Products:Glass:Glasswear:Drinking Glasses"
USE:
ary.partial_include? string
The first item in the array will return true, it does not need to match the entire string.
class Array
def partial_include? search
self.each do |e|
return true if search.include?(e.to_s)
end
return false
end
end
If you don't mind to monkeypatch the the Array class you could do it like this
test = ["i am a boy" , "i am a girl"]
class Array
def partial_include? search
self.each do |e|
return true if e[search]
end
return false
end
end
p test.include?("boy") #==>false
p test.include?("frog") #==>false
p test.partial_include?("boy") #==>true
p test.partial_include?("frog") #==>false
If you want to test if a word included into the array elements, you can use method like this:
def included? array, word
array.inject([]) { |sum, e| sum + e.split }.include? word
end