I come from the Java world so I was shocked to discover that arrays (http://ruby-doc.org/core/classes/Array.html) does not hava a method contains(object) returning bool.
What is the good way - the Ruby way - of doing that ?
array.include?(obj) → true or false
Returns true if the given object is present in self (that is, if any object == anObject), false otherwise.
a = [ "a", "b", "c" ]
a.include?("b") #=> true
a.include?("z") #=> false
This, from the Array class documentation:
[1,2,3].include? 2
=> true
ruby-1.9.2-p0 > [1,2,3].include? 3
=> true
ruby-1.9.2-p0 > [1,2,3].include? 33
=> false
You can do this:
Array.index("ITEM")
if the result is != de nil the element exists.
Regards.
Related
I'm doing a ruby challenge that I found on rubeque.com. Here are the instructions:
Instructions:
Write a method #r_empty? that returns true if a hash and its subhashes are empty or false if there is a value in the hash.
My Answer:
class Hash
def r_empty?
def recurse(h)
h.each {|key, value|
value.is_a?(Hash) ? recurse(value) :
if (value!=nil && value!="")
#puts value
return false
end
}
return true
end
recurse(self)
end
end
Test:
a = {:ruby => "", :queue => ""}
b = {:ruby => {:version => {:one => {"nine" => ""}, "two" => "=^.^="}},
:html => ""}
c = {:pets => {:dogs => {:my => {"niko" => ""}, "ollie" => ""}}, :cats =>
nil, :mice => ""}
d = {a: "", b: :two, c: ""}
Answers:
a.r_empty?, true
b.r_empty?, false
c.r_empty?, true
d.r_empty?, false
({}.r_empty?), true
Using this code, I was able to get the right answer for 4 out of the 5 tests. My method returns TRUE for b.r_empty? ... I do notice that if I uncomment out #puts value, "=^.^=" is printed out for b.r_empty? ... So the if statement is being executed, but ultimately false is not returned. I'm still a ruby novice so I will gladly appreciate any advice and guidance towards the right topics i should go over for this challenge.
Although it's cool to define a method inside another (I did not know this was possibly actually) the method can be simplified quite a bit:
class Hash
def r_empty?
!values.any? do |val|
val.is_a?(Hash) ? !val.r_empty? : (val && val != "")
end
end
end
I'm not sure exactly the problem is with your original code, however I think the recurse(value) is effectively being discarded.
By the way, in terms of style I recommend only using a ternary for single-line expressions and also being diligent about consistent indentation.
I have a string which is passed as a parameter to a function. Here, I want to check if the string contains only numbers. So I had a check like below:
def check_string(string)
result = false
if string.to_i.to_s.eql? string
result = true
end
result
end
But the problem arises when a string starts with 0. In that case, a false is returned.
check_string('123') #=> true
check_string('0123') #=> false
How can I solve this issue?
You can try the following
def check_string(string)
string.scan(/\D/).empty?
end
It would be truthy if string contains only digits or if it is an empty string. Otherwise returns false.
A number can be negative, or a float. So if these are allowed, consider this solution:
def is_numberic?(str)
str == "#{str.to_f}" || str == "#{str.to_i}"
end
some input which evaluate to true
pry(main)> is_numberic? '5'
=> true
pry(main)> is_numberic? '58127721'
=> true
pry(main)> is_numberic? '58127721.737673'
=> true
pry(main)> is_numberic? '0'
=> true
pry(main)> is_numberic? '1818'
=> true
pry(main)> is_numberic? '0.1'
=> true
pry(main)> is_numberic? '0.0'
=> true
pry(main)> is_numberic? '11.29'
=> true
pry(main)> is_numberic? '-0.12'
=> true
pry(main)> is_numberic? '-29'
=> true
the input which evaluate to false
pry(main)> is_numberic? '10 years'
=> false
pry(main)> is_numberic? '01'
=> false
pry(main)> is_numberic? '00'
=> false
pry(main)> is_numberic? '0.10'
=> false
pry(main)> is_numberic? ''
=> false
As you can see, there're several cases which probably should be supported, eg '0.10', but are not. In this case, the permitted input is '0.1'.
def check_string(str)
str !~ /\D/
end
check_string '123'
#=> true
check_string ''
#=> true
check_string '1a2'
#=> false
this is my proposition for detecting if it's a float number
def check(string)
scan = string.scan(/\D/)
scan.size == 0 || (scan.size == 1 && scan.first == ".") # or "," depend on your separator
end
example of use:
check("123") => true
check("12.3") => true
check("12e3") => false
check("12.3.2") => false
EDIT: 2023
After some years i see this is the most compact solution:
def check_string(str)
str.scan(/\D/).empty?
end
You can use Regexp for it:
def check_string(string)
raise 'Empty string passed' if string.empty?
/\A\d+\z/ === string
end
check_string '123'
#=> true
check_string '0123'
#=> true
check_string '0'
#=> true
We can also use the "match" function to do this.
"1234".match(/\D/)
#=> nil
"1234foo".match(/\D/)
#=> #<MatchData "f">
match (String) - APIdock
I think we should use the regex to find this.
it will work for the below scenarios
"3.0"
"av3"
"3"
is_numeric = false if option.option.match?(/[^0-9.]/)
If anyone is searching for another way to determine if string is numeric -> is to use "is_a? Numeric". Is_a? reference documentation
"namaste".is_a? Numeric
=> false
6.is_a? Numeric
=> true
str1 = "foo"
str2 = 9
str1.is_a? Numeric
=> false
str2.is_a? Numeric
=> true
You can also use:
7.is_a?(Numeric)
=> true
"too".is_a?(Numeric)
=> false
Basically it's determining if a class is a type of class object. I just found this and thought I would share.
I cannot find a way to determine if a key-value pair exists in a hash.
h4 = { "a" => 1, "d" => 2, "f" => 35 }
I can use Hash#has_value? and Hash#has_key? to find information about a key or a value individually, but how can I check if a pair exists?
Psuedo-code of what I'm after:
if h4.contains_pair?("a", 1)
Just use this:
h4['a'] == 1
It seems excessive to me, but you could monkey-patch Hash with a method like so:
class Hash
def contains_pair?(key, value)
key?(key) && self[key] == value
end
end
I confess to starting down a road and then wondering where it might take me. This may not be the best way of determining if a key/value pair is present in a hash (how could one improve on #Jordan's answer?), but I learned something along the way.
Code
def pair_present?(h,k,v)
Enumerable.instance_method(:include?).bind(h).call([k,v])
end
Examples
h = { "a"=>1, "d"=>2, "f"=>35 }
pair_present?(h,'a',1)
#=> true
pair_present?(h,'f',36)
#=> false
pair_present?(h,'hippopotamus',2)
#=> false
Discussion
We could of course convert the hash to an array and then apply Array#include?:
h.to_a.include?(['a', 1])
#=> true
but that has the downside of creating a temporary array. It would be nice if the class Hash had such an instance method, but it does not. One might think Hash#include? might be used for that, but it just takes one argument, a key.1.
The method Enumerable#include? does what we want, and of course Hash includes the Enumerable module. We can invoke that method in various ways.
Bind Enumerable#include? to the hash and call it
This was of course my answer:
Enumerable.instance_method(:include?).bind(h).call([k,v])
Use the method Method#super_method, which was introduced in v2.2.
h.method(:include?).super_method.call(['a',1])
#=> true
h.method(:include?).super_method.call(['a',2])
#=> false
Note that:
h.method(:include?).super_method
#=> #<Method: Object(Enumerable)#include?>
Do the alias_method/remove_method merry-go-round
Hash.send(:alias_method, :temp, :include?)
Hash.send(:remove_method, :include?)
h.include?(['a',1])
#=> true
h.include?(['a',2])
#=> false
Hash.send(:alias_method, :include?, :temp)
Hash.send(:remove_method, :temp)
Convert the hash to an enumerator and invoke Enumerable#include?
h.to_enum.include?(['a',1])
#=> true
h.to_enum.include?(['a',2])
#=> false
This works because the class Enumerator also includes Enumerable.
1 Hash#include? is the same as both Hash#key? and Hash#has_key?. It makes me wonder why include? isn't used for the present purpose, since determining if a hash has a given key is well-covered.
How about using Enumerable any?
h4 = { "a" => 1, "d" => 2, "f" => 35 }
h4.any? {|k,v| k == 'a' && v == 1 }
Given I have the below clients hash, is there a quick ruby way (without having to write a multi-line script) to obtain the key given I want to match the client_id? E.g. How to get the key for client_id == "2180"?
clients = {
"yellow"=>{"client_id"=>"2178"},
"orange"=>{"client_id"=>"2180"},
"red"=>{"client_id"=>"2179"},
"blue"=>{"client_id"=>"2181"}
}
Ruby 1.9 and greater:
hash.key(value) => key
Ruby 1.8:
You could use hash.index
hsh.index(value) => key
Returns the key for a given value. If
not found, returns nil.
h = { "a" => 100, "b" => 200 }
h.index(200) #=> "b"
h.index(999) #=> nil
So to get "orange", you could just use:
clients.key({"client_id" => "2180"})
You could use Enumerable#select:
clients.select{|key, hash| hash["client_id"] == "2180" }
#=> [["orange", {"client_id"=>"2180"}]]
Note that the result will be an array of all the matching values, where each is an array of the key and value.
You can invert the hash. clients.invert["client_id"=>"2180"] returns "orange"
You could use hashname.key(valuename)
Or, an inversion may be in order. new_hash = hashname.invert will give you a new_hash that lets you do things more traditionally.
try this:
clients.find{|key,value| value["client_id"] == "2178"}.first
According to ruby doc http://www.ruby-doc.org/core-1.9.3/Hash.html#method-i-key key(value) is the method to find the key on the base of value.
ROLE = {"customer" => 1, "designer" => 2, "admin" => 100}
ROLE.key(2)
it will return the "designer".
From the docs:
(Object?) detect(ifnone = nil) {|obj| ... }
(Object?) find(ifnone = nil) {|obj| ... }
(Object) detect(ifnone = nil)
(Object) find(ifnone = nil)
Passes each entry in enum to block. Returns the first for which block is not false. If no object matches, calls ifnone and returns its result when it is specified, or returns nil otherwise.
If no block is given, an enumerator is returned instead.
(1..10).detect {|i| i % 5 == 0 and i % 7 == 0 } #=> nil
(1..100).detect {|i| i % 5 == 0 and i % 7 == 0 } #=> 35
This worked for me:
clients.detect{|client| client.last['client_id'] == '2180' } #=> ["orange", {"client_id"=>"2180"}]
clients.detect{|client| client.last['client_id'] == '999999' } #=> nil
See:
http://rubydoc.info/stdlib/core/1.9.2/Enumerable#find-instance_method
The best way to find the key for a particular value is to use key method that is available for a hash....
gender = {"MALE" => 1, "FEMALE" => 2}
gender.key(1) #=> MALE
I hope it solves your problem...
Another approach I would try is by using #map
clients.map{ |key, _| key if clients[key] == {"client_id"=>"2180"} }.compact
#=> ["orange"]
This will return all occurences of given value. The underscore means that we don't need key's value to be carried around so that way it's not being assigned to a variable. The array will contain nils if the values doesn't match - that's why I put #compact at the end.
Heres an easy way to do find the keys of a given value:
clients = {
"yellow"=>{"client_id"=>"2178"},
"orange"=>{"client_id"=>"2180"},
"red"=>{"client_id"=>"2179"},
"blue"=>{"client_id"=>"2181"}
}
p clients.rassoc("client_id"=>"2180")
...and to find the value of a given key:
p clients.assoc("orange")
it will give you the key-value pair.
EDIT : First part removed i found the answer.
I have the following problem : im reading a number from the input and trying to use that number to access a given array position. I get the following results
value #=> "0"
value.to_i #=> 0
myArray[0] #=> MyObject
myArray[value.to_i] #=> nil
That works for me.
irb(main):012:0> myArray = ['first']
=> ["first"]
irb(main):013:0> value = '0'
=> "0"
irb(main):014:0> myArray[value.to_i]
=> "first"
Try myArray[Integer(value)] (although value.to_i works for me as well):
>> value = "0"
=> "0"
>> myArray = ["a", "b"]
=> ["a", "b"]
>> myArray[0]
=> "a"
>> myArray[Integer(value)]
=> "a"
Thank you for all your replies, i was trying to access and array inside a class variable with:
#myclass.myarray[value]
when i made a getter method and accessed myarray inside the object the error disappeared. If anyone can explain this behavior please let me know