Removing multiple zeros from a string if only zeros are input - ruby

I'm trying to implement a method that if the user inputs a series of zero like "00000" it should return "0"
Otherwise, if the user inputs for example "00009" or "90000", the input variable should remain unchanged.
Is there a simple solution for this problem?

def doit(str)
str.squeeze == '0' ? '0' : str
end
doit("00000") #=> "0"
doit("00009") #=> "00009"
doit("90000") #=> "90000"
See the last sentence of the doc String#squeeze.

Try this
"0000000".gsub(/^0+$/, '0')
=> "0"
"0000009".gsub(/^0+$/, '0')
=> "0000009"
=> "0"
"9000000".gsub(/^0+$/, '0')
=> "9000000"

You can do it using regular expressions as follow:
def validate_sequence(sequence:)
r = /\A(^0+[1-9]+\z)|(\A[1-9]+[0-9]+\z)/
sequence.match?(r) ? sequence : '0'
end
The code above returns the same sequence if the sequence matches the regex or 0 in another case, the regex validates that a sequence is a valid number or if end with a valid sequence of numbers, the double ? change the result of the match function and returns a boolean value.
You can use the code above as follow: validate_sequence(sequence: '0000000')
If you want to only match digits distinct of 0 at the beginning and at the end you can do it by changing the value of r like this: r = /(^0+[1-9]+$)|(^[1-9]+0+$)/.

When the string always contains only digits then you might want to consider:
sequence.to_i.zero? ? '0' : sequence
IMHO it is always interesting to run a benchmark when there are so many different solutions
require 'benchmark/ips'
Benchmark.ips do |x|
examples = %w[00000 00001 12345]
def cary_swoveland(str)
str.squeeze == '0' ? '0' : str
end
def r4cc00n(str)
r = /(^0+[1-9]+$)|(^[1-9]+[0-9]+$)/
!!str.match(r) ? str : '0'
end
def spickermann(str)
str.to_i.zero? ? '0' : str
end
def ursus(str)
str.gsub(/^0+$/, '0')
end
%w[cary_swoveland r4cc00n spickermann ursus].each do |algorithm|
x.report(algorithm) { examples.each { |e| send(algorithm, e) } }
end
x.compare!
end
Result:
$ ruby benchmark.rb
Warming up --------------------------------------
cary_swoveland 86.149k i/100ms
r4cc00n 24.258k i/100ms
spickermann 94.211k i/100ms
ursus 21.714k i/100ms
Calculating -------------------------------------
cary_swoveland 833.459k (± 2.2%) i/s - 4.221M in 5.067333s
r4cc00n 231.787k (± 6.9%) i/s - 1.164M in 5.050636s
spickermann 905.658k (±10.0%) i/s - 4.522M in 5.097849s
ursus 213.674k (± 2.3%) i/s - 1.086M in 5.083811s
Comparison:
spickermann: 905658.0 i/s
cary_swoveland: 833459.1 i/s - same-ish: difference falls within error
r4cc00n: 231787.4 i/s - 3.91x (± 0.00) slower
ursus: 213674.2 i/s - 4.24x (± 0.00) slower

Related

In ruby , How do you check if an input is a float or a string ? [duplicate]

Is there a way to simply check if a string value is a valid float value. Calling to_f on a string will convert it to 0.0 if it is not a numeric value. And using Float() raises an exception when it is passed an invalid float string which is closer to what I want, but I don't want to handle catching exceptions. What I really want is a method such as nan? which does exist in the Float class, but that doesn't help because a non-numeric string cannot be converted to a float without being changed to 0.0 (using to_f).
"a".to_f => 0.0
"a".to_f.nan? => false
Float("a") => ArgumentError: invalid value for Float(): "a"
Is there a simple solution for this or do I need to write code to check if a string is a valid float value?
Here's one way:
class String
def valid_float?
# The double negation turns this into an actual boolean true - if you're
# okay with "truthy" values (like 0.0), you can remove it.
!!Float(self) rescue false
end
end
"a".valid_float? #false
"2.4".valid_float? #true
If you want to avoid the monkey-patch of String, you could always make this a class method of some module you control, of course:
module MyUtils
def self.valid_float?(str)
!!Float(str) rescue false
end
end
MyUtils.valid_float?("a") #false
An interesting fact about the Ruby world is the existence of the Rubinius project, which implements Ruby and its standard library mostly in pure Ruby. As a result, they have a pure Ruby implementation of Kernel#Float, which looks like:
def Float(obj)
raise TypeError, "can't convert nil into Float" if obj.nil?
if obj.is_a?(String)
if obj !~ /^\s*[+-]?((\d+_?)*\d+(\.(\d+_?)*\d+)?|\.(\d+_?)*\d+)(\s*|([eE][+-]?(\d+_?)*\d+)\s*)$/
raise ArgumentError, "invalid value for Float(): #{obj.inspect}"
end
end
Type.coerce_to(obj, Float, :to_f)
end
This provides you with a regular expression that matches the internal work Ruby does when it runs Float(), but without the exception. So you could now do:
class String
def nan?
self !~ /^\s*[+-]?((\d+_?)*\d+(\.(\d+_?)*\d+)?|\.(\d+_?)*\d+)(\s*|([eE][+-]?(\d+_?)*\d+)\s*)$/
end
end
The nice thing about this solution is that since Rubinius runs, and passes RubySpec, you know this regex handles the edge-cases that Ruby itself handles, and you can call to_f on the String without any fear!
Ruby 2.6+
Ruby 2.6 added a new exception keyword argument to Float.
So, now to check whether a string contains a valid float is as simple as:
Float('22.241234', exception: false)
# => 22.241234
Float('abcd', exception: false)
# => nil
Here is a link to the docs.
# Edge Cases:
# numeric?"Infinity" => true is_numeric?"Infinity" => false
def numeric?(object)
true if Float(object) rescue false
end
#Possibly faster alternative
def is_numeric?(i)
i.to_i.to_s == i || i.to_f.to_s == i
end
I saw the unresolved discussion on cast+exceptions vs regex and I thought I would try to benchmark everything and produce an objective answer:
Here is the source for the best case and worst of each method attempted here:
require "benchmark"
n = 500000
def is_float?(fl)
!!Float(fl) rescue false
end
def is_float_reg(fl)
fl =~ /(^(\d+)(\.)?(\d+)?)|(^(\d+)?(\.)(\d+))/
end
class String
def to_float
Float self rescue (0.0 / 0.0)
end
end
Benchmark.bm(7) do |x|
x.report("Using cast best case") {
n.times do |i|
temp_fl = "#{i + 0.5}"
is_float?(temp_fl)
end
}
x.report("Using cast worst case") {
n.times do |i|
temp_fl = "asdf#{i + 0.5}"
is_float?(temp_fl)
end
}
x.report("Using cast2 best case") {
n.times do |i|
"#{i + 0.5}".to_float
end
}
x.report("Using cast2 worst case") {
n.times do |i|
"asdf#{i + 0.5}".to_float
end
}
x.report("Using regexp short") {
n.times do |i|
temp_fl = "#{i + 0.5}"
is_float_reg(temp_fl)
end
}
x.report("Using regexp long") {
n.times do |i|
temp_fl = "12340918234981234#{i + 0.5}"
is_float_reg(temp_fl)
end
}
x.report("Using regexp short fail") {
n.times do |i|
temp_fl = "asdf#{i + 0.5}"
is_float_reg(temp_fl)
end
}
x.report("Using regexp long fail") {
n.times do |i|
temp_fl = "12340918234981234#{i + 0.5}asdf"
is_float_reg(temp_fl)
end
}
end
With the following results with mri193:
user system total real
Using cast best case 0.608000 0.000000 0.608000 ( 0.615000)
Using cast worst case 5.647000 0.094000 5.741000 ( 5.745000)
Using cast2 best case 0.593000 0.000000 0.593000 ( 0.586000)
Using cast2 worst case 5.788000 0.047000 5.835000 ( 5.839000)
Using regexp short 0.951000 0.000000 0.951000 ( 0.952000)
Using regexp long 1.217000 0.000000 1.217000 ( 1.214000)
Using regexp short fail 1.201000 0.000000 1.201000 ( 1.202000)
Using regexp long fail 1.295000 0.000000 1.295000 ( 1.284000)
Since we are dealing with only Linear time algorithms I think we use empirical measurements to make generalizations. It is plain to see that regex is more consistent and will only fluctuate a bit based on the length of the string passed. The cast is clearly faster when there are no failure, and much slower when there are failures.
If we compare the success times we can see that the cast best case is about .3 seconds faster than regex best case. If we divide this by the amount of time in the case worst case we can estimate how many runs it would take to break even with exceptions slowing the cast down to match regex speeds. About 6 seconds dived by .3 gives us about 20. So if performance matters and you expect less than 1 in 20 of your test to fail then used cast+exceptions.
JRuby 1.7.4 has completely different results:
user system total real
Using cast best case 2.575000 0.000000 2.575000 ( 2.575000)
Using cast worst case 53.260000 0.000000 53.260000 ( 53.260000)
Using cast2 best case 2.375000 0.000000 2.375000 ( 2.375000)
Using cast2 worst case 53.822000 0.000000 53.822000 ( 53.822000)
Using regexp short 2.637000 0.000000 2.637000 ( 2.637000)
Using regexp long 3.395000 0.000000 3.395000 ( 3.396000)
Using regexp short fail 3.072000 0.000000 3.072000 ( 3.073000)
Using regexp long fail 3.375000 0.000000 3.375000 ( 3.374000)
Cast is only marginally faster in the best case (about 10%). Presuming this difference is appropriate for making generalizations(I do not think it is), then the break even point is somewhere between 200 and 250 runs with only 1 causing an exception.
So exceptions should only be used when truly exceptional things happens, this is decision for you and your codebase. When they aren't used code they are in can be simpler and faster.
If performance doesn't matter, you should probably just following whatever conventions you team or code base already has and ignore this whole answers.
def float?(string)
true if Float(string) rescue false
end
This supports 1.5, 5, 123.456, 1_000 but not 1 000, 1,000, etc. (e.g. same as String#to_f).
>> float?("1.2")
=> true
>> float?("1")
=> true
>> float?("1 000")
=> false
>> float?("abc")
=> false
>> float?("1_000")
=> true
Source: https://github.com/ruby/ruby/blob/trunk/object.c#L2934-L2959
Umm, if you don't want exceptions then perhaps:
def is_float?(fl)
fl =~ /(^(\d+)(\.)?(\d+)?)|(^(\d+)?(\.)(\d+))/
end
Since OP specifically asked for a solution without exceptions. Regexp based solution is marginally slow:
require "benchmark"
n = 500000
def is_float?(fl)
!!Float(fl) rescue false
end
def is_float_reg(fl)
fl =~ /(^(\d+)(\.)?(\d+)?)|(^(\d+)?(\.)(\d+))/
end
Benchmark.bm(7) do |x|
x.report("Using cast") {
n.times do |i|
temp_fl = "#{i + 0.5}"
is_float?(temp_fl)
end
}
x.report("using regexp") {
n.times do |i|
temp_fl = "#{i + 0.5}"
is_float_reg(temp_fl)
end
}
end
Results:
5286 snippets:master!? %
user system total real
Using cast 3.000000 0.000000 3.000000 ( 3.010926)
using regexp 5.020000 0.000000 5.020000 ( 5.021762)
Try this
def is_float(val)
fval = !!Float(val) rescue false
# if val is "1.50" for instance
# we need to lop off the trailing 0(s) with gsub else no match
return fval && Float(val).to_s == val.to_s.gsub(/0+$/,'') ? true:false
end
s = "1000"
is_float s
=> false
s = "1.5"
is_float s
=> true
s = "Bob"
is_float s
=> false
n = 1000
is_float n
=> false
n = 1.5
is_float n
=> true
I tried to add this as a comment but apparently there is no formatting in comments:
on the other hand, why not just use that as your conversion function, like
class String
def to_float
Float self rescue (0.0 / 0.0)
end
end
"a".to_float.nan? => true
which of course is what you didn't want to do in the first place. I guess the answer is, "you have to write your own function if you really don't want to use exception handling, but, why would you do that?"

Ruby - Cannot sum up hash values

I'm new to Ruby (and programming in general). I have a hash that is using data from an external file, and I'm trying to get the total number of values that are greater than 1500.
Here's my code Actually, I need both the number of entries and the total value of purchase orders over 1500. The external file is just a column of order numbers and a column of prices. I'm sure there is a very simple solution, but like I said I'm a beginner and can't figure it out. Any help would be appreciated. Thanks.
Edit: Here is my code. It's just that last while loop that's causing all the problems. I know that's not the right way to go about it, but I just can't figure out what to do.
myhash={}
file=File.open("Purchase Orders.csv", "r")
while !file.eof
line=file.readline
key,value=line.chomp.split(",")
myhash[key]=value
end
total=0
entries=myhash.length
newtotal=0
myhash.each { |key,value|
total+=value.to_f
}
puts total
puts entries
while value.to_f>1500
myhash.each {|key,value| newtotal+=value.to_f}
end
puts newtotal
I will rewrite the code in ruby idiomatic way in hope you’ll examine it and find out some hints.
prices = File.readlines("Purchase Orders.csv").map do |line|
line.chomp.split(",").last.to_f
end # array of prices
total = prices.inject(:+) # sum values
pricy = prices.select { |v| v > 1500 }
pricy_sum = pricy.inject(:+) # sum expensives
pricy_count = pricy.length # expensives’ size
puts "Total sum is: #{total}"
puts "Total expensives is: #{pricy}"
looks like you have your loops reversed. Also, using do and end is usually preferred over curly braces for multiline code blocks, while curly braces are generally used for single line blocks (as noted by #mudasobwa). Check out the ruby style guide for some more style pointers.
myhash.each do |key,value|
newtotal+=value.to_f if value.to_f > 1500
end
puts newtotal
Code
def nbr_and_tot(fname)
File.foreach(fname).with_object({ nbr_over: 0, tot_over: 0 }) do |line, h|
n = line[/\d+/].to_i
if n > 1500
h[:nbr_over] += 1
h[:tot_over] += n
end
end
end
Example
First let's create a file "temp":
str =<<-END
:cat, 1501
:dog, 1500
:pig, 2000
END
File.write("temp", str)
#=> 33
Confirm the file is correct:
puts File.read("temp")
prints
:cat, 1501
:dog, 1500
:pig, 2000
Now execute the method.
nbr_and_tot "temp"
#=> {:nbr_over=>2, :tot_over=>3501}
Explanation
First review, as necessary, IO::foreach, which reads the file line-by-line1 and returns an enumerator that is chained to with_object, Enumerator#with_object and String#[].
For the example,
fname = "temp"
e0 = File.foreach(fname)
#=> #<Enumerator: File:foreach("temp")>
We can see the values that will be generated by this enumerator (and passed to each_object) by converting it to an array:
e0.to_a
#=> [":cat, 1501\n", ":dog, 1500\n", ":pig, 2000\n"]
Continuing,
e1 = e0.with_object({ nbr_over: 0, tot_over: 0 })
#=> #<Enumerator: #<Enumerator: 2.3.0 :171 >
e1.to_a
#=> [[":cat, 1501\n", {:nbr_over=>0, :tot_over=>0}],
# [":dog, 1500\n", {:nbr_over=>0, :tot_over=>0}],
# [":pig, 2000\n", {:nbr_over=>0, :tot_over=>0}]]
The first element generated by e1 is passed to the block and the block variables are assigned values, using parallel assignment:
line, h = e1.next
#=> [":cat, 1501\n", {:nbr_over=>0, :tot_over=>0}]
line
#=> ":cat, 1501\n"
h #=> {:nbr_over=>0, :tot_over=>0}
and n is computed:
s = line[/\d+/]
#=> "1501"
n = s.to_i
#=> 1501
As n > 1500 #=> true, we perform the following operations:
h[:nbr_over] += 1
#=> 1
h[:tot_over] += n
#=> 1501
so now
h #=> {:nbr_over=>1, :tot_over=>1501}
Now the second element of e1 is passed to the block and the following steps are performed:
line, h = e1.next
#=> [":dog, 1500\n", {:nbr_over=>1, :tot_over=>1501}]
line
#=> ":dog, 1500\n"
h #=> {:nbr_over=>1, :tot_over=>1501}
n = line[/\d+/].to_i
#=> 1500
As n > 1500 #=> fasle, this line is skipped. The processing of the last element generated by e1 is similar to that for the first element.
1 File is a subclass of IO (File < IO #=> true), so IO class methods such as foreach are often invoked on the File class (File.foreach...).

How do you use split and scan to parse a URI in ruby?

Let's say I have this string in Ruby
str = "/server/ab/file.html
I want to get an array that contains
["/server/", "/ab/", "file.html"]
Is there a way to obtain this array using split or scan? I have tried all kinds of combinations with nothing matching exactly what I want. I can't use any outside libraries. Any ideas? Thanks.
As #sawa stated, the issue is with the double '/' that requires you to manipulate the string.
The most direct solution I can think of is:
# removes the '/' at the beginning of the string
# and splits the string to an array
a = str.sub(/^\//, '').split('/') # => ["server", "ab", "file.html"]
# iterates through the array objects EXCEPT the last one,
# (notice three dots '...' instead of two '..'),
# and adds the missing '/'
a[0...-1].each {|s| s << '/'; s.insert(0 , '/')} # => ["/server/", "/ab/"]
a # => ["/server/", "/ab/", "file.html"]
EDIT 2
Following up with #mudasobwa's concepts, ideas and inputs, if you know that the first character is always a '/', this would be fastest solution so far (see edited benchmark):
a = str[1..-1].split('/')
a << (a.pop.tap { a.map! {|s| "/#{s}/" } } )
Good Luck.
Benchmarks
After reading #mudasobwa's answer I was super impressed. I wanted to know how much faster his solution was...
... and I was surprised to see that although his solution is much more elegant looking, it's substantially slower.
I have no idea why, but it seems that the Regexp lookup using gsub or scan is slower in this case.
Here's the benchmark, for anyone interested (iterations per second - higher numbers are better):
require 'benchmark/ips'
str = "/server/ab/file.html"
Benchmark.ips do |b|
b.report("split") do
a = str.sub(/^\//, '').split('/')
a[0...-1].each {|s| s << '/'; s.insert(0 , '/')}
end
b.report("updated split") do
a = str[1..-1].split('/')
a[0...-1].each {|s| s << '/'; s.insert(0 , '/')}
end
b.report("scan") do
str.scan(/(?<=\/)([\w.]+)(\/)?/).map { |(val,slash)| slash ? "/#{val}/" : val }
end
b.report("gsub") do
str.gsub(/(?<=\/)([\w.]+)(\/)?/).map { |m| "#{$2 && '/'}#{m}" }
end
b.report("mudasobwa's varient") do
a = str[1..-1].split('/')
[*a[0..-2].map { |e| "/#{e}/"}, a[-1]]
end
b.report("mudasobwa's tap concept") do
a = str[1..-1].split('/')
a << (a.pop.tap { a.map! {|s| "/#{s}/" } })
end
end; nil
# results:
#
# Calculating -------------------------------------
# split 39.378k i/100ms
# updated split 45.530k i/100ms
# scan 23.910k i/100ms
# gsub 18.006k i/100ms
# mudasobwa's varient 47.389k i/100ms
# mudasobwa's tap concept
# 51.895k i/100ms
# -------------------------------------------------
# split 517.487k (± 2.9%) i/s - 2.599M
# updated split 653.271k (± 6.4%) i/s - 3.278M
# scan 268.048k (± 6.9%) i/s - 1.339M
# gsub 202.457k (± 3.2%) i/s - 1.026M
# mudasobwa's varient 656.734k (± 4.8%) i/s - 3.317M
# mudasobwa's tap concept
# 761.914k (± 3.2%) i/s - 3.840M
▶ str.gsub(/(?<=\/)([\w.]+)(\/)?/).map { |m| "#{$2 && '/'}#{m}" }
#⇒ [ "/server/", "/ab/", "file.html" ]
or, with scan, that is more semantic:
▶ str.scan(/(?<=\/)([\w.]+)(\/)?/).map { |(val,slash)| slash ? "/#{val}/" : val }
Probably the fastest solution:
▶ a = str[1..-1].split('/')
▶ [*a[0..-2].map { |e| "/#{e}/"}, a[-1]]
#⇒ ["/server/", "/ab/", "file.html"]
Complete inplace array change (hey, aesthetes):
▶ a = str[1..-1].split('/')
▶ a.pop.tap do |e|
▷ a.map! do |e|
▷ [-1, 0].each do |i|
▷ e.insert(i, '/')
▷ end
▷ e
▷ end.push e
▷ end
▶ puts a
#⇒ ["/server/", "/ab/", "file.html"]
str = str[1..-1].split('/')
=> ["server", "ab", "file.html"]
str[0...-1].map!{|e| "/#{e}/"} << str[-1]
=> ["/server/", "/ab/", "file.html"]

Which way is efficient for storing in hash?

Assume my_hash = {:name => "bob", :age => 21}. I can assign values to the hash in three ways:
Way 1
my_hash[:name] = "bob"
my_hash[:age] = 21
Way 2
my_hash.store(:name,"bob")
my_hash.store(:age,21)
Way 3
my_hash = {:name => "bob", :age => 21}
Please help me understand value assignment in terms of OS memory. Why are there three ways to assign values to keys, and which way is efficient?
Incase of memory i believe all takes equal memory. I benchmarked each step and these are the results. As you can see speed for each case is just marginally different, not enough difference to choose one over the other.
So you just use the code that you feel natural when writing your code.
user system total real
0.760000 0.030000 0.790000 ( 0.808573) my_hash[:t] = 1
0.810000 0.030000 0.840000 ( 0.842075) my_hash.store(:t, 1)
0.750000 0.020000 0.770000 ( 0.789766) my_hash = {:t => 1}
benchmarking script.
require 'benchmark'
Benchmark.bm do |x|
x.report do
1000000.times do
my_hash = {}
my_hash[:t] = 1
my_hash[:b] = 2
end
end
x.report do
1000000.times do
my_hash = {}
my_hash.store(:t, 1)
my_hash.store(:b, 2)
end
end
x.report do
1000000.times do
my_hash = {:t => 1, :t => 2}
end
end
end
I prefer benchmark-ips for this sort of thing, because it works out how many times the test should be performed and it also gives you some error margins. For this
Benchmark.ips do |x|
x.report('[]') do |n|
n.times do
t = {}
t[:x] = 1
end
end
x.report('store') do |n|
n.times do
t = {}
t.store(:x, 1)
end
end
end
produces
[] 2.082M (±14.6%) i/s - 10.276M
store 1.978M (±13.9%) i/s - 9.790M
i.e. the difference is well within the margin of error, This isn't surprising because if you look at the source then you can see that []= and store are actually exactly the same method.

How do I pick randomly from an array?

I want to know if there is a much cleaner way of doing this. Basically, I want to pick a random element from an array of variable length. Normally, I would do it like this:
myArray = ["stuff", "widget", "ruby", "goodies", "java", "emerald", "etc" ]
item = myArray[rand(myarray.length)]
Is there something that is more readable / simpler to replace the second line? Or is that the best way to do it. I suppose you could do myArray.shuffle.first, but I only saw #shuffle a few minutes ago on SO, I haven't actually used it yet.
Just use Array#sample:
[:foo, :bar].sample # => :foo, or :bar :-)
It is available in Ruby 1.9.1+. To be also able to use it with an earlier version of Ruby, you could require "backports/1.9.1/array/sample".
Note that in Ruby 1.8.7 it exists under the unfortunate name choice; it was renamed in later version so you shouldn't use that.
Although not useful in this case, sample accepts a number argument in case you want a number of distinct samples.
myArray.sample(x) can also help you to get x random elements from the array.
myArray.sample
will return 1 random value.
myArray.shuffle.first
will also return 1 random value.
Random Number of Random Items from an Array
def random_items(array)
array.sample(1 + rand(array.count))
end
Examples of possible results:
my_array = ["one", "two", "three"]
my_array.sample(1 + rand(my_array.count))
=> ["two", "three"]
=> ["one", "three", "two"]
=> ["two"]
Here are some benchmark tests I performed on some of the answers posted here, using sample was consistently faster than the rest.
test_arr = ["stuff", "widget", "ruby", "goodies", "java", "emerald" ]
Benchmark.ips do |x|
x.report("1 - sample") { test_arr.sample }
x.report("2 - shuffle") { test_arr.shuffle.first }
x.report("3 - length") { rand(test_arr.length) }
x.report("4 - rand rand") { test_arr.sample(1 + rand(test_arr.count)) }
x.report("5 - rand el") { test_arr[rand(test_arr.count)]}
x.report("6 - switch") {
case rand(0..test_arr.length)
when 0
test_arr[0]
when 1
test_arr[1]
when 2
test_arr[2]
when 3
test_arr[3]
when 4
test_arr[4]
when 5
test_arr[5]
end
}
x.compare!
The tests were run on a MacBook Pro (15-inch, 2018), 2.6 GHz 6-Core Intel Core i7, 32 GB 2400 MHz DDR4
Warming up --------------------------------------
1 - sample 713.455k i/100ms
2 - shuffle 253.848k i/100ms
3 - length 489.078k i/100ms
4 - rand rand 236.396k i/100ms
5 - rand el 447.244k i/100ms
6 - switch 419.272k i/100ms
Calculating -------------------------------------
1 - sample 7.505M (± 3.2%) i/s - 37.813M in 5.044078s
2 - shuffle 2.661M (± 2.1%) i/s - 13.454M in 5.057659s
3 - length 5.021M (± 1.6%) i/s - 25.432M in 5.066159s
4 - rand rand 2.352M (± 2.4%) i/s - 11.820M in 5.029415s
5 - rand el 4.452M (± 2.2%) i/s - 22.362M in 5.025623s
6 - switch 4.324M (± 1.1%) i/s - 21.802M in 5.043294s
Comparison:
1 - sample: 7504636.7 i/s
3 - length: 5021326.6 i/s - 1.49x (± 0.00) slower
5 - rand el: 4452078.6 i/s - 1.69x (± 0.00) slower
6 - switch: 4323511.6 i/s - 1.74x (± 0.00) slower
2 - shuffle: 2661267.7 i/s - 2.82x (± 0.00) slower
4 - rand rand: 2351630.7 i/s - 3.19x (± 0.00) slower
arr = [1,9,5,2,4,9,5,8,7,9,0,8,2,7,5,8,0,2,9]
arr[rand(arr.count)]
This will return a random element from array.
If You will use the line mentioned below
arr[1+rand(arr.count)]
then in some cases it will return 0 or nil value.
The line mentioned below
rand(number)
always return the value from 0 to number-1.
If we use
1+rand(number)
then it may return number and arr[number] contains no element.
class String
def black
return "\e[30m#{self}\e[0m"
end
def red
return "\e[31m#{self}\e[0m"
end
def light_green
return "\e[32m#{self}\e[0m"
end
def purple
return "\e[35m#{self}\e[0m"
end
def blue_dark
return "\e[34m#{self}\e[0m"
end
def blue_light
return "\e[36m#{self}\e[0m"
end
def white
return "\e[37m#{self}\e[0m"
end
def randColor
array_color = [
"\e[30m#{self}\e[0m",
"\e[31m#{self}\e[0m",
"\e[32m#{self}\e[0m",
"\e[35m#{self}\e[0m",
"\e[34m#{self}\e[0m",
"\e[36m#{self}\e[0m",
"\e[37m#{self}\e[0m" ]
return array_color[rand(0..array_color.size)]
end
end
puts "black".black
puts "red".red
puts "light_green".light_green
puts "purple".purple
puts "dark blue".blue_dark
puts "light blue".blue_light
puts "white".white
puts "random color".randColor

Resources