Hi people!
See my nifty little class for converting a few time strings to
seconds. See how the last line of self.seconds reverses an array and
then adds up each part, multiplying the first with 1, the second with
60 and the third with 60*60. So 1:25:20 is a total of one hour, 25
minutes and 20 seconds - all converted to seconds.
Now look how I have to make a magical auto-incrementing counter
variable because inject doesn’t provide the element index. Is there a
better way than this? Should I write an inject_with_index?
Les
Seconder.seconds parses time formats and converts them to seconds,
returning a string representation. It accepts:
10:25:05
17d (17 days)
10h (10 hours)
25m
5s
25:05
5
class Seconder
DURATIONS = {‘s’ => 1, ‘m’ => 60, ‘h’ => 6060, ‘d’ => 6060*24}
def self.count
@counter += 1
end
def self.seconds(string)
if string !~
/^\d+$|^\d{1,2}:\d{1,2}$|^\d{1,2}:\d{1,2}:\d{1,2}$|^\d+s$|^\d+h$|^\d+m$|^\d+d$/
return “Format incorrect, try 10:25:05 for hh:mm:ss or 10h for 10
hours”
end
lastChar = string[-1,1]
if DURATIONS.has_key?(lastChar) && string.length > 1
firstChars = string[0..-2]
return (firstChars.to_i * DURATIONS[lastChar]).to_s
end
@counter = 0
string.split(":").reverse.map{|part| part.to_i}.inject{|sum, part|
sum + part * 60 ** count}
end
end
On 8/12/06, James Edward G. II [email protected] wrote:
(“A”…“D”).inject_with_index(“”) do |str, (let, i)|
?> i % 2 == 0 ? str += let : str
end
=> “AC”
That most certainly does!
Les
On 8/12/06, Leslie V. [email protected] wrote:
=> nil
(“A”…“D”).inject_with_index(“”) do |str, (let, i)|
?> i % 2 == 0 ? str += let : str
end
=> “AC”
What I don’t understand about your solution is the “do |str, (let, i)|”,
how can you have brackets in there? What does that do?
Your example works as above but I can’t get it to work with an array.
Here’s what I get:
p [1,3,5].inject_with_index{|sum, (part, index)| sum + part}
=> seconderc.rb:46:in `+': can’t convert Fixnum into Array (TypeError)
p [1,3,5].inject_with_index{|sum, part, index| sum + part}
=> [1, 0, 3, 1, 5, 2]
My own inject is a lot clunkier (and takes no params) but seems to work:
def inject_with_index
total = self[0]
index = 1
loop do
break if index == self.length
total = yield(total, self[index], index)
index += 1
end
total
end
public :inject_with_index
p [1,3,5].inject_with_index{|sum, part, index| sum + part}
=> 9
Les
On Aug 12, 2006, at 3:22 PM, Leslie V. wrote:
end
=> nil
(“A”…“D”).inject_with_index("") do |str, (let, i)|
?> i % 2 == 0 ? str += let : str
end
=> “AC”
What I don’t understand about your solution is the “do |str, (let,
i)|”,
how can you have brackets in there? What does that do?
I used the parens to split the arguments, as you can in Ruby
assignments.
Your example works as above but I can’t get it to work with an array.
Here’s what I get:
p [1,3,5].inject_with_index{|sum, (part, index)| sum + part}
=> seconderc.rb:46:in `+’: can’t convert Fixnum into Array (TypeError)
This expression uses inject’s default behavior to setup sum, but
remember that elements are now paired with their index. sum is thus
initialized to [1, 0], which blows up your later math. You can fix
this by initializing sum yourself:
[1,3,5].inject_with_index(0) {|sum, (part, index)| sum + part}
James Edward G. II