Fastest way to find a String into an array of string - ruby

The script has to verify if one predefined IP is present in a big array of IPs. Currently I code that function like this (saying that "ips" is my array of IP and "ip" is the predefined ip)
ips.each do |existsip|
if ip == existsip
puts "ip exists"
return 1
end
end
puts "ip doesn't exist"
return nil
Is there a faster way to do the same thing?
Edit : I might have wrongly expressed myself. I can do array.include? but what I'd like to know is : Is array.include? the method that will give me the fastest result?

You can use Set. It is implemented on top of Hash and will be faster for big datasets - O(1).
require 'set'
s = Set.new ['1.1.1.1', '1.2.3.4']
# => #<Set: {"1.1.1.1", "1.2.3.4"}>
s.include? '1.1.1.1'
# => true

You could use the Array#include method to return you a true/false.
http://ruby-doc.org/core-1.9.3/Array.html#method-i-include-3F
if ips.include?(ip) #=> true
puts 'ip exists'
else
puts 'ip doesn\'t exist'
end

A faster way would be:
if ips.include?(ip)
puts "ip exists"
return 1
else
puts "ip doesn't exist"
return nil
end

ips = ['10.10.10.10','10.10.10.11','10.10.10.12']
ip = '10.10.10.10'
ips.include?(ip) => true
ip = '10.10.10.13'
ips.include?(ip) => false
check Documentaion here

have you tried the Array#include? function?
http://ruby-doc.org/core-1.9.3/Array.html#method-i-include-3F
You can see from the source it does almost exactly the same thing, except natively.

Related

Check whether string match or not

I have a string and an array with some strings.
as below
hostname = TETDC3DBE01
Array = ['WEB','APP','STR','DBE']
I want to find whether that hostname match with any of the array element or not?
When I'm trying with below code getting output
no
no
no
no
Here is loop repeating each and every element on array. I want check that hostname with single check on array the produce the output either yes or no only.
Array.each do |x|
if hostname.match(x)
puts "yes"
else
puts "no"
end
end
Given this fixed Ruby code:
hostname = 'TETDC3DBE01'
array = ['WEB','APP','STR','DBE']
Where if you want to find all elements in array that match as a substring of hostname your code should work. The more minimal matching system is probably:
array.select { |x| hostname.match(x) }
# => ["DBE"]
Using a tool like puts to produce output isn't always very useful because that "yes" or "no" text can't be acted upon by more code. Try and think of Ruby programs as a chain of transformations, where this selects all matches, and later you can print them, like this:
puts array.select { |x| hostname.match(x) }.join(',')
# => DBE
Check out Array#any? method.
It passes each element of the collection to the given block. The method returns true if the block ever returns a value other than false or nil. If the block is not given, Ruby adds an implicit block of { |obj| obj } that will cause any? to return true if at least one of the collection members is not false or nil.
If instead a pattern is supplied, the method returns whether pattern === element for any collection member.
In your case:
hostname = 'TETDC3DBE01'
['WEB','APP','STR','DBE'].any? do |x|
hostname.match(x)
end
or even if you actually mean equal by match:
hostname = 'TETDC3DBE01'
['WEB','APP','STR','DBE'].any?(hostname)
Lets take your code to fix it.
hostname = "TETDC3DBE01"
arr = ['WEB','APP','STR','DBE']
arr.each do |x|
if hostname.match?(x)
puts "yes"
else
puts "no"
end
end
match gives array of result and
match? gives you true or false value
I wouldn't use regexp in this case. A simple String#include? is probably faster. Furthermore any? will return true if any of the elements in the array leads is matching.
hostname = 'TETDC3DBE01'
array = ['WEB','APP','STR','DBE']
array.any? { |x| hostname.include?(x) }
#=> true
Regular expression made real easy:
hostname = "TETDC3DBE01"
array = ['WEB','APP','STR','DBE']
re = Regexp.union(array)
hostname.match?(re) # => true

Ruby net-ping usage confusion

I'm trying to figure out how to use the net/ping gem and I have a couple of questions since I've been using it:
Why do you need admin privileges to run ICMP
Does it return true or false? For example:
Net::Ping::ICMP.new("127.0.0.1").ping?# <= true
#So I could do something like this:
ping = Net::Ping::ICMP.new("127.0.0.1")
if ping == true
puts "true"
else
puts "This shouldn't run"
end
#<= true
#or does it return packets received?
#so I could do something like this:
ping = Net::Ping::ICMP.new("127.0.0.1")ping?
if ping =~ /Received = 1/
puts "true"
else
puts "This shouldn't run"
end
#<= true
I'm confused and I can't seem to find anything on google pertaining to how it works: https://www.google.com/search?safe=off&btnG=Search&q=ruby+net%3A%3Aping%3A%3Aicmp+tutorial
If someone could help me it would be greatly appreciated, thank you
This is how ruby evals if:
irb> ping = true
=> true
irb > ping =~ /Received = 1/
=> nil
irb> nil ? "NIL is true" : "NIL is not true"
=> "NIL is not true"
Result of match true is nil, and if nil is false. So, your second example will always outputs "true" (even if .ping? will be false).
And 'admin privileges': you cannot create ICMP packet as normal user. Unless you use /bin/ping which is SUID. (which net/ping gem don't use). `.

What is the elegant "Ruby Way" of handling nil values?

So I want to conditionally assign variables based on whether or not the input has been given.
For example
#name = params[:input]['name'] || "Name not yet given"
However, if the params have not been passed yet, this gives an error
method [] does not exist for nil class
I have two ideas to get around this. One is adding a [] method to nil class. Something like:
class NilClass
def []
self
end
end
And the other idea that I have is to use if statements
if params[:input].nil?
#name = params[:input]['name']
else
#name = "Name not yet given"
end
However, neither of these solutions feel quite right.
What is the "ruby way"?
One way is use Hash#fetch.
params[:input].to_h.fetch('name', "Name not yet given")
You can always write some code to sweeten your other code.
class Hash
def deep_fetch(*path)
path.reduce(self) { |memo, elem| memo ? memo[elem] : nil }
end
end
params = { input: { name: 'sergio' } }
params.deep_fetch(:input, :name) # => "sergio"
params.deep_fetch(:omg, :lol, :wtf) # => nil
#name = params[:input].nil? ? "Name not yet given" : params[:input]['name']
With current application, .nil? may optionally be excluded.
Also see my solution for recursions: https://stackoverflow.com/a/24588976/445221
I like to use NullObjects, or, more specifically, Black Hole objects for this sort of thing. Avdi Grimm has blessed us with a great ruby gem for this construct called naught. So for your situation, I'd install the gem and then start by creating my project-specific Null Object:
# add this to a lib file such as `lib/null_object.rb`
require 'naught'
NullObject = Naught.build do |config|
config.define_explicit_conversions
config.define_implicit_conversions
config.black_hole
if $DEBUG
config.traceable
else
config.singleton
end
end
Then, include NullObject::Conversions where needed and go to town, confidently!
# my_class.rb
require 'null_object.rb'
include NullObject::Conversions
Maybe(params[:input])["name"].to_s.presence || "Name not yet given"
# => "Name not yet given"
The great thing about this Black Hole approach is that there's no extra steps needed for any additional chaining. You simply chain methods together as long as you want under the (confident) assumption that it will turn out well. Then, at the end you convert the value to the expected type and the explicit conversions will give you a basic version of that back if something in the chain returned nil before you expected it to.
Maybe(params[:thing1])[:thing2][:thing3].map(&:to_i).sum.to_i
# => 0
Or, if you prefer, you can use Actual to convert a Black Hole object back to its actual value:
Actual(Maybe(params[:input])["name"]) || "Name not yet given"
For more on the Null Object pattern, check out Avdi Grimm's post on the subject. All in all it's a great way to gain confidence and stop type checking (and remember, even checking for nil as with .try() is type checking!). Duck typing is supposed to free us from type checking!
As I understand, for the hash h, you want to know if
h has a key :input and if so
h[:input] is a hash and if so
h[:input] has a key "name"
If "yes" to all three, return h[:input]["name"]; else return "Name not yet given".
So just write that down:
def get_name(h)
if (h[:input].is_a? Hash) && h[:input].key?("name")
h[:input]["name"]
else
"Name not yet given"
end
end
params = { hat: "cat" }
get_name(params)
#=> "Name not yet given"
params = { input: "cat" }
get_name(params)
#=> "Name not yet given"
params = { input: {} }
get_name(params)
#=> "Name not yet given"
params = { input: { "moniker"=>"Jake" } }
get_name(params)
#=> "Name not yet given"
params = { input: { "name"=>"cat" } }
get_name(params)
#=> "cat"
Another way:
def get_name(h)
begin
v = h[:input]["name"]
v ? v : "Name not yet given"
rescue NoMethodError
"Name not yet given"
end
end
You could use Hash#dig introduced in Ruby 2.3.0.
#name = params.dig(:input, 'name') || "Name not yet given"
Similarly if you want to gracefully handle nil returns when chaining methods, you can use the safe navigation operator also introduced in Ruby 2.3.0.
#name = object&.input&.name || "Name not yet given"
Try to fetch the key:
params[:input].try(:fetch, 'name', "Name not yet given")
Assuming you are on rails which seems likely, otherwise you can concatenate fetchs:
params.fetch(:input, {}).fetch 'name', "Name not yet given"
It's a common practice to define params like this:
def input_params
params.fetch(:input, {})
end
Which reduces the problem to:
input_params[:name] || 'Whatever'

Regular expression to validate IPv4 address in ruby [duplicate]

This question already has answers here:
How do I check whether a value in a string is an IP address
(13 answers)
Closed 8 years ago.
I want to verify whether a given string is valid IPv4 address or not in ruby.
I tried as follows but what is does is matches values greater than 255 as well.
How to limit each block's range from 0-255
str="255.255.255.256"
if str=~ /\b[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\b/
puts true
else
puts false
end
You have the IPAddr class in Ruby. You do not need to validate it agains a regex, just create a new object and catch the exception when it fails:
require 'ipaddr'
ip = IPAddr.new "127.0.0.1"
# => #<IPAddr: IPv4:127.0.0.1/255.255.255.255>
ip = IPAddr.new "127.0.0.a"
# => IPAddr::InvalidAddressError: invalid address
block = /\d{,2}|1\d{2}|2[0-4]\d|25[0-5]/
re = /\A#{block}\.#{block}\.#{block}\.#{block}\z/
re =~ "255.255.255.255" # => 0
re =~ "255.255.255.256" # => nil
You'd better to use ruby core class IPAddress
you could do it this way:
require "ipaddress"
IPAddress.valid? "192.128.0.12"
#=> true
IPAddress.valid? "192.128.0.260"
#=> false
you could find more here How do I check whether a value in a string is an IP address
This is a way that reads pretty easily:
str.count('.')==3 && str.split('.').all? {|s| s[/^\d{3}$/] && s.to_i < 256}

Checking if a variable is defined?

How can I check whether a variable is defined in Ruby? Is there an isset-type method available?
Use the defined? keyword (documentation). It will return a String with the kind of the item, or nil if it doesn’t exist.
>> a = 1
=> 1
>> defined? a
=> "local-variable"
>> defined? b
=> nil
>> defined? nil
=> "nil"
>> defined? String
=> "constant"
>> defined? 1
=> "expression"
As skalee commented: "It is worth noting that variable which is set to nil is initialized."
>> n = nil
>> defined? n
=> "local-variable"
This is useful if you want to do nothing if it does exist but create it if it doesn't exist.
def get_var
#var ||= SomeClass.new()
end
This only creates the new instance once. After that it just keeps returning the var.
The correct syntax for the above statement is:
if (defined?(var)).nil? # will now return true or false
print "var is not defined\n".color(:red)
else
print "var is defined\n".color(:green)
end
substituting (var) with your variable. This syntax will return a true/false value for evaluation in the if statement.
defined?(your_var) will work. Depending on what you're doing you can also do something like your_var.nil?
Try "unless" instead of "if"
a = "apple"
# Note that b is not declared
c = nil
unless defined? a
puts "a is not defined"
end
unless defined? b
puts "b is not defined"
end
unless defined? c
puts "c is not defined"
end
WARNING Re: A Common Ruby Pattern
the defined? method is the answer. See the accepted answer above.
But watch out... consider this common ruby pattern:
def method1
#x ||= method2
end
def method2
nil
end
method2 always returns nil.
The first time you call method1, the #x variable is not set - therefore method2 will be run. and
method2 will set #x to nil.
But what happens the second time you call method1?
Remember #x has already been set to nil. But method2 will still be run again!! If method2 is a costly undertaking this might not be something that you want.
Let the defined? method come to the rescue:
def method1
return #x if defined? #x
#x = method2
end
As with most things, the devil is in the implementation details.
Use defined? YourVariable
Keep it simple silly .. ;)
Here is some code, nothing rocket science but it works well enough
require 'rubygems'
require 'rainbow'
if defined?(var).nil? # .nil? is optional but might make for clearer intent.
print "var is not defined\n".color(:red)
else
print "car is defined\n".color(:green)
end
Clearly, the colouring code is not necessary, just a nice visualation in this toy example.
You can try:
unless defined?(var)
#ruby code goes here
end
=> true
Because it returns a boolean.
As many other examples show you don't actually need a boolean from a method to make logical choices in ruby. It would be a poor form to coerce everything to a boolean unless you actually need a boolean.
But if you absolutely need a boolean. Use !! (bang bang) or "falsy falsy reveals the truth".
› irb
>> a = nil
=> nil
>> defined?(a)
=> "local-variable"
>> defined?(b)
=> nil
>> !!defined?(a)
=> true
>> !!defined?(b)
=> false
Why it doesn't usually pay to coerce:
>> (!!defined?(a) ? "var is defined".colorize(:green) : "var is not defined".colorize(:red)) == (defined?(a) ? "var is defined".colorize(:green) : "var is not defined".colorize(:red))
=> true
Here's an example where it matters because it relies on the implicit coercion of the boolean value to its string representation.
>> puts "var is defined? #{!!defined?(a)} vs #{defined?(a)}"
var is defined? true vs local-variable
=> nil
It should be mentioned that using defined to check if a specific field is set in a hash might behave unexpected:
var = {}
if defined? var['unknown']
puts 'this is unexpected'
end
# will output "this is unexpected"
The syntax is correct here, but defined? var['unknown'] will be evaluated to the string "method", so the if block will be executed
edit: The correct notation for checking if a key exists in a hash would be:
if var.key?('unknown')
Please note the distinction between "defined" and "assigned".
$ ruby -e 'def f; if 1>2; x=99; end;p x, defined? x; end;f'
nil
"local-variable"
x is defined even though it is never assigned!
defined? is great, but if you are in a Rails environment you can also use try, especially in cases where you want to check a dynamic variable name:
foo = 1
my_foo = "foo"
my_bar = "bar"
try(:foo) # => 1
try(:bar) # => nil
try(my_foo) # => 1
try(my_bar) # => nil
Also, you can check if it's defined while in a string via interpolation, if you code:
puts "Is array1 defined and what type is it? #{defined?(#array1)}"
The system will tell you the type if it is defined.
If it is not defined it will just return a warning saying the variable is not initialized.
Hope this helps! :)
Leaving an incredibly simple example in case it helps.
When variable doesn't exist:
if defined? a then "hi" end
# => nil
When variable does exist:
a = 2
if defined? a then "hi" end
# => "hi"

Resources