2017-10-17 34 views
0

J'essaie de faire mes devoirs et je voudrais demander si vous pouvez m'aider à écrire un Ruby Proc qui renvoie le nombre (Entier , Float, ...) et les chaînes de chiffres ("22") multipliées par 2 et la chaîne de texte ("sos") reviennent simplement inchangées. J'essaye de faire cela avec l'opérateur unaire mais je ne travaille pas avec Float.Ruby Proc qui renvoie les nombres et les chaînes de chiffres multiplié par 2 comme type non déployé et texte strng retourne juste

def make_double 
    proc = Proc.new { |x| (x.is_a? Integer or x !~ /\D/) ? ((x.to_i)*2).to_s : x } 
end 

Existe-t-il une possibilité d'écrire des conditions plus complexes dans proc? Merci

+0

Désolé, je suis un peu perdu à ce que vous attendez ce faire exactement. Peut-être quelques exemples d'entrées/sorties pourraient aider? Aussi, y a-t-il une raison pour laquelle vous avez condensé le tout sur une seule ligne? Je pense que le problème est définitivement dans votre x! ~/\ D /. Le '.to_i' va aussi avoir besoin d'être' .to_f' du son de celui-ci. Je pense que vous devriez vérifier http://rubular.com/ pour la regex mais peut-être quelque chose comme '\ d + (?: \. \ D +)?'? – user3334690

+0

J'ai juste besoin de ceci par exemple –

+0

p = make_double ;;; p.call (42) -> 84 ;;; p.call (42.0) -> 84.0 ;;; p.call ("42") -> "84.0" ;;; p.call ("Univers") -> "Univers" ;;; et Cela doit être fait avec Proc –

Répondre

2

Lisible

puts '-- do block --' 

def make_double 
    Proc.new do | x | 
     case x 
     when Integer, Float then x * 2 
     when String 
      if x =~ /\d/ 
      then (x.to_i * 2).to_s 
      else x 
      end 
     else 
      "Invalid class #{x.class.name} for x." 
     end 
    end 
end 

puts "42 -> #{make_double.call(42)}  #{make_double.call(42).class}" 
puts "42.0 -> #{make_double.call(42.0)} #{make_double.call(42.0).class}" 
puts "'42' -> #{make_double.call('42')}  #{make_double.call('42').class}" 
puts "'xyz' -> #{make_double.call('xyz')} #{make_double.call('xyz').class}" 
puts "4..8 -> #{make_double.call(4..8)}" 

Exécution:

$ ruby -w t_a.rb 
-- do block -- 
42 -> 84  Integer 
42.0 -> 84.0 Float 
'42' -> 84  String 
'xyz' -> xyz String 
4..8 -> Invalid class Range for x. 

Difficile à lire

puts '-- brace block --' 

def make_double 
    Proc.new { | x | x.is_a?(Integer) || x.is_a?(Float) ? x * 2 : \ 
     x.is_a?(String) ? x =~ /\d/ ? (x.to_i * 2).to_s : x : 'invalid' } 
end 

puts "42 -> #{make_double.call(42)}  #{make_double.call(42).class}" 
puts "42.0 -> #{make_double.call(42.0)} #{make_double.call(42.0).class}" 
puts "'42' -> #{make_double.call('42')}  #{make_double.call('42').class}" 
puts "'xyz' -> #{make_double.call('xyz')} #{make_double.call('xyz').class}" 
puts "4..8 -> #{make_double.call(4..8)}" 

Exécution:

$ ruby -w t.rb 
-- brace block -- 
42 -> 84  Integer 
42.0 -> 84.0 Float 
'42' -> 84  String 
'xyz' -> xyz String 
4..8 -> invalid 
+0

Oui, cela fonctionne très bien, merci! –

+0

Qu'en est-il de 'make_double.call (" 42.5 ")' ne sais pas si cette affaire est importante. Je pense que vous pouvez aussi gagner du temps en faisant tout d'abord une ficelle. Quelque chose comme: '(x.to_s = ~ /\d+(?:\.\d+)?/)? x.to_f * 2: x' – user3334690

+1

@ user3334690 Droit! Comme l'OP ne l'a pas demandé, je ne l'ai pas testé, et mon 'if x = ~/\ d /' est insuffisant. Ajout d'une réponse plus complète. – BernardK

1

Cette réponse prend en compte le commentaire de @ user3334690 et corrige des résultats erronés pour

puts "'42xyz' -> #{make_double.call('42xyz')} #{make_double.call('42xyz').class}" 
puts "'x42y' -> #{make_double.call('x42y')}  #{make_double.call('x42y').class}" 
puts "'42.5' -> #{make_double.call('42.5')} #{make_double.call('42.5').class}" 

qui étaient

'42xyz' -> 84 String 
'x42y' -> 0  String 
'42.5' -> 84 String 

One-liner

puts '-- brace block 2 --' 

def make_double 
    Proc.new { | x | (x.to_s =~ /\d+(?:\.\d+)?/) ? x.to_f * 2 : x rescue puts "Error" } 
end 

puts "42 -> #{make_double.call(42)}   #{make_double.call(42).class}" 
puts "42.0 -> #{make_double.call(42.0)}   #{make_double.call(42.0).class}" 
puts "'42' -> #{make_double.call('42')}   #{make_double.call('42').class}" 
puts "'42xyz' -> #{make_double.call('42xyz')}  #{make_double.call('42xyz').class}" 
puts "'x42y' -> #{make_double.call('x42y')}  #{make_double.call('x42y').class}" 
puts "'42.5' -> #{make_double.call('42.5')}  #{make_double.call('42.5').class}" 
puts "'42.5xyz' -> #{make_double.call('42.5xyz')} #{make_double.call('42.5xyz').class}" 
puts "'xyz' -> #{make_double.call('xyz')}   #{make_double.call('xyz').class}" 
puts "4..8 -> #{make_double.call(4..8)}" 

Exécution:Notez que tous les nombres et toutes les chaînes contenant des nombres sont convertis en nombres flottants et que x42y est converti en 0.0.

Conserver la classe originale

cordes mélange chiffres et de lettres ne sont pas convertis (en utilisant des ancres^et dans la regexp $).

puts '-- do block 2 --' 

def make_double 
    Proc.new do | x | 
     case x 
     when Integer, Float then x * 2 
     when String 
      case 
      when x =~ /^\d+\.\d+$/ then (x.to_f * 2).to_s 
      when x =~ /^\d+$/  then (x.to_i * 2).to_s 
      else x 
      end 
     else 
      "Invalid class #{x.class.name} for x." 
     end 
    end 
end 

puts "42 -> #{make_double.call(42)}    #{make_double.call(42).class}" 
puts "42.0 -> #{make_double.call(42.0)}   #{make_double.call(42.0).class}" 
puts "'42' -> #{make_double.call('42')}   #{make_double.call('42').class}" 
puts "'42xyz' -> #{make_double.call('42xyz')}  #{make_double.call('42xyz').class}" 
puts "'x42y' -> #{make_double.call('x42y')}  #{make_double.call('x42y').class}" 
puts "'42.5' -> #{make_double.call('42.5')}  #{make_double.call('42.5').class}" 
puts "'42.5xyz' -> #{make_double.call('42.5xyz')} #{make_double.call('42.5xyz').class}" 
puts "'xyz' -> #{make_double.call('xyz')}   #{make_double.call('xyz').class}" 
puts "4..8 -> #{make_double.call(4..8)}" 

Exécution:

$ ruby -w t_b.rb 
-- do block 2 -- 
42 -> 84    Fixnum 
42.0 -> 84.0   Float 
'42' -> 84   String 
'42xyz' -> 42xyz  String 
'x42y' -> x42y  String 
'42.5' -> 85.0  String 
'42.5xyz' -> 42.5xyz String 
'xyz' -> xyz   String 
4..8 -> Invalid class Range for x.