I need to create the following Array:
array_time = [00:00:00, 00:00:01, ..., 23:59:59]
Is there a way to generate this type of hash with all hours of the day in ruby?
Because then I will need to create the following Hash:
hash = { "time" => { "'00:00:00'" => "23:59:59" } }
And I would like to check if the sub-Hash under key "time"
uses keys in the correct format, for example:
hash["time"].each do |key|
array_time.includes key
end
CodePudding user response:
Assuming that you're happy with Strings, this is a simple way to do it:
array_time = ("00".."23").flat_map do |h|
("00".."59").flat_map do |m|
("00".."59").map do |s|
"#{h}:#{m}:#{s}"
end
end
end
array_time.length
# => 86400
array_time.first(5)
# => ["00:00:00", "00:00:01", "00:00:02", "00:00:03", "00:00:04"]
array_time.last(5)
#=> ["23:59:55", "23:59:56", "23:59:57", "23:59:58", "23:59:59"]
However, if your goal is:
and I would like to check if the hash time is in the correct format, example:
hash["time"].each do |key| array_time.include? key end
Then that's really not the most efficient way to go about it.
First off, Hash lookups are much faster than Array#include?
, so you really want to use a Hash and treat it a Set:
time_set = Hash[
("00".."23").flat_map do |h|
("00".."59").flat_map do |m|
("00".."59").map do |s|
["#{h}:#{m}:#{s}", true]
end
end
end
]
time_set
# => {"00:00:00"=>true,
# "00:00:01"=>true,
# "00:00:02"=>true,
# ...
# "23:59:58"=>true,
# "23:59:59"=>true}
And then perform your lookups like this:
hash[:time].each do |time_str|
time_set[time_str]
end
But even this is not great. Not always at least.
If you know you need to perform this check very often, with arbitrary values, and with a lot of values to check, then yes, pre-computing the lookup set once and storing it in a constant could make sense. So you'd use TIME_SET = ...
instead of time_set = ...
.
But if this is performed sporadically, you're just much better off validating the time strings one by one. For example:
TIME_REGEX = %r{^([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$}.freeze
hash[:time].each do |time_str|
TIME_REGEX === time_str
end
CodePudding user response:
Assuming an array of strings is acceptable, here is one way to do it.
time_iterator = Time.at(1_500_076_800) # 2017-07-15 00:00:00 0000
end_time = time_iterator 1.day
array_time = []
while time_iterator < end_time
array_time << time_iterator.strftime('%T')
time_iterator = 1.second
end
Apparently in Ruby 1.9 they removed the ability to step-iterate over a time range, so a while loop seems to be preferred now.
I do think that if you're just trying to validate the format of a time-like string (HH:MM:SS) then there are much better ways to accomplish this. A simple RegEx would do it, or something similar.