2010-02-02 4 views
0

Je voudrais tourner une chaîne avec des heures d'ouverture comme ceci:Chaîne à matrice et Hash avec Regexp

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

Dans ceci:

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

Je suis en train avec le String.scan() mais ne peut pas comprendre l'expression rationnelle.

Aussi, si vous avez des suggestions sur la façon de le faire inverse de la meilleure façon (à savoir lors de l'obtention des heures d'ouverture d'une forme.)

Mise à jour - Merci à vous tous trouvé des solutions parfaites! En ce moment, j'utilise (merci kejadlen):

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

Mais que diriez-vous renverser =) Donc, étant donné:

[ {: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"} ] 

Je veux fusionner à:

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

Vous devriez vraiment ouvrir une autre question pour le renverser, mais ... 'aire. map {| i | "% s>% s-% s"% i [: période], je [: ouvre], je [: ferme]} .join (";") ' – kejadlen

Répondre

0

Essayez ceci:

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

M Il faut jouer avec l'expression rationnelle un peu plus mais ça devrait le faire.

Modifier - Eh bien, vous avez demandé la réponse dans le contexte de rubis et je vous ai donné la réponse Java, mais l'expression régulière doit travailler de toute façon ...

+0

um, sauf que je devine que l'OQ voulait un tableau de hachages en sortie, pas une sérialisation de chaîne qui a besoin d'être évaluée. – p00ya

+0

@ P00ya - Vous avez raison ... n'était pas clair cependant. – Ben

2

voilà comment je le ferais

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"}] 
+3

Juste pour le plaisir ... 'periods = str.split (';'). Inject ([]) {| n, i | n << Hash [* [: période,: heures] .zip (i.split ('>')). aplatir]}) ' – kejadlen

+4

Ou ...' str.scan (/ ([\ w -] +) > ([\ d: -] +) /). map {| (p, h) | {: period => p,: heures => h}} ' – kejadlen

+0

Oui, ça vaut vraiment le coup pour le plaisir :). Ruby nous permet de mettre une longue chaîne de méthodes sur une seule ligne mais je ne pense pas qu'il soit prudent de tout mettre en ligne si l'intention de votre code devient un peu confuse. J'essaie de mettre les choses dans des variables temporaires avant d'appeler une autre méthode si cela rend l'intention du code un peu plus claire.Par exemple, si vous regardez mon code, il indique clairement ce qu'il fait au moment où vous le regardez, d'abord couper la chaîne par ';' et créez un tableau, puis scindez '>' pour créer chaque élément du tableau et créez un hash. Il suffit de suivre les principes du code propre – nas

3

Si vous préférez 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:

En ce qui concerne l'inverse, cela devrait faire le travail:

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" 
0

Cela ressemble à cela fonctionne

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"}] 
0
str.scan(/([\w-]+)>([\d:-]+)/).map {|(p,h)| {:period => p, :hours => h }} 
Questions connexes