0

I would like to turn a string with opening hours like this:

"Monday-Friday>10:00-18:00;Saturday>12:00-17:00;Sunday>12:00-15:00"

Into this:

[ {:period => "Monday-Friday", :hours => "10:00-18:00"}, {:period => "Saturday", :hours => "12:00-17:00"}, {:period => "Sunday", :hours => "12:00-15:00"} ]

I'm trying it with the String.scan() method but can't figure out the Regexp.

Also if you have any suggestions of how to do it in reverse the best way (i.e. when getting the opening hours from a form.)

Update - Thank you all found perfect solutions! Right now I'm using (thanks kejadlen):

str.scan(/([\w-]+)>([\d:-]+)-([\d:]+)/).map { |(p,o,c)| {:period => p, :opens => o, :closes => c} }

But now how about reversing it =) So given:

[ {:opens=>"10:00", :closes=>"18:00", :period=>"Monday-Friday"}, 
  {:opens=>"12:00", :closes=>"17:00", :period=>"Saturday"}, 
  {:opens=>"12:00", :closes=>"15:00", :period=>"Sunday"} ]

I want to merge it to:

"Monday-Friday>10:00-18:00;Saturday>12:00-17:00;Sunday>12:00-15:00"
1
  • You really should open another question for reversing it, but... ary.map {|i| "%s>%s-%s" % i[:period], i[:opens], i[:closes] }.join(";") Commented Feb 2, 2010 at 20:42

5 Answers 5

3

If you prefer one-liners:

s = "Monday-Friday>10:00-18:00;Saturday>12:00-17:00;Sunday>12:00-15:00"
s.split(/;/).map{|i| Hash[[[:period, :hours], i.split(/>/)].transpose]}
# or
s.split(/;/).map{|i| p, h = i.split(/>/); {:period => p, :hours => h}}
#=> [{:period=>"Monday-Friday", :hours=>"10:00-18:00"}, {:period=>"Saturday", :hours=>"12:00-17:00"}, {:period=>"Sunday", :hours=>"12:00-15:00"}]

Edit:

Regarding the reverse, this should do the job:

a.map{|i| "#{i[:period]}>#{i[:opens]}-#{i[:closes]}"}.join(';')
=> "Monday-Friday>10:00-18:00;Saturday>12:00-17:00;Sunday>12:00-15:00"
Sign up to request clarification or add additional context in comments.

Comments

2

this is how I would do it

str="Monday-Friday>10:00-18:00;Saturday>12:00-17:00;Sunday>12:00-15:00"
periods = str.split(';') 
#=> ["Monday-Friday>10:00-18:00", "Saturday>12:00-17:00", "Sunday>12:00-15:00"]
period_array=[]
periods.each do |period| 
  period_with_hours = period.split('>')
  period_array << {:period =>  period_with_hours.first, :hours => period_with_hours.last}
end

period_array

#=> [{:period=>"Monday-Friday", :hours=>"10:00-18:00"}, {:period=>"Saturday", :hours=>"12:00-17:00"}, {:period=>"Sunday", :hours=>"12:00-15:00"}]

5 Comments

Just for fun... periods = str.split(';').inject([]) {|n,i| n << Hash[*[:period, :hours].zip(i.split('>')).flatten] })
Or... str.scan(/([\w-]+)>([\d:-]+)/).map {|(p,h)| {:period => p, :hours => h }}
Yes, that definitely valid for fun :). Ruby allows us to put a long chain of methods on a single line but I think its not prudent to put everything on a line if the intention of your code gets a bit muddled. I try to put things in temporary variables before calling another method on it if that makes the intention of the code a bit more clear. For instance, if you look at my code, it clearly says what it is doing the moment you look at it, first split string by ';' and create an array and then split on '>' to create each element of the array and create hash.Just following clean code principles
You don't have to write it in a single line. Functional-style solutions (using map, inject etc.) are considered more elegant and thus preferred among Rubyists.
@Mladen I do agree with that as long as the code intention is clear
0

Try this:

String S =  ([^\>]*)\>([^\;]*)\;
String T = " {:period => $1, :hours => $2}, "
originalString.replaceAll(S,T);

Might have to play with the regexp a little more but that should about do it.

Edit - Well, you asked for the answer in the context of ruby and I gave you the Java answer but the regular expression should work anyway...

1 Comment

um, except that I'm guessing the OQ wanted an array of hashes as output, not a string serialisation that needs eval'ing.
0

This looks like it works

the_input.split(';').collect{|pair|
    period, hours = pair.split('>')
    {:period => period, :hours => hours}
}
=> [{:hours=>"10:00-18:00", :period=>"Monday-Friday"}, {:hours=>"12:00-17:00", :
period=>"Saturday"}, {:hours=>"12:00-15:00", :period=>"Sunday"}]

Comments

0
str.scan(/([\w-]+)>([\d:-]+)/).map {|(p,h)| {:period => p, :hours => h }}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.