Is there better way to replace these case statement?

Is there better way to replace these case statement?

case cmd
          when /^Astro$/
                toolName = 'astro'

          when /^core/
                toolName = 'coretools'

          when /^(fm_shell|formality)$/
                toolName = 'fm'

          when /^gca_shell$/
                toolName = 'gcas'
    ......

          when /^xa/
                toolName = 'xa'

          else
                toolName = ''

end

···

--
Posted via http://www.ruby-forum.com/.

Not perfect, but something you could start with:

result = cmd[ /\A(astro|core|fm_shell|formality|gca_shell|xa)\z/i, 1 ]

···

--
Posted via http://www.ruby-forum.com/.

cmd="Astro"

#decode
code_book={ Astro: "astro", core: "coretools", fm_shell: "fm", formality: "fm" }
tool_name = code_book[cmd.to_sym]

#output
puts tool_name

The downside I see here is it returns nil instead of "" if there is no matching.

J.T

···

-----Original Message-----
From: ruby-talk [mailto:ruby-talk-bounces@ruby-lang.org] On Behalf Of Previn Lin
Sent: Friday, December 20, 2013 2:58 AM
To: ruby-talk@ruby-lang.org
Subject: Is there better way to replace these case statement?

Is there better way to replace these case statement?

case cmd
          when /^Astro$/
                toolName = 'astro'

          when /^core/
                toolName = 'coretools'

          when /^(fm_shell|formality)$/
                toolName = 'fm'

          when /^gca_shell$/
                toolName = 'gcas'
    ......

          when /^xa/
                toolName = 'xa'

          else
                toolName = ''

end

--
Posted via http://www.ruby-forum.com/.

I see it's better don't use long case statement, is there good way to do
refactor on case statement with regular expression?

···

--
Posted via http://www.ruby-forum.com/.

Can we do like the way below? How to process the Regular express in it?

def eat(fruit_code)
  fruit_type =
    case fruit_code
     when 'a'
       Apple
     when 'b'
      Banana
     when 'c'
      Coconut
     when 'o'
      Orange
    end
end

=>

FRUIT_TYPES=
  { 'a' => Apple, 'b' => Banana, 'c' => Coconut, 'o' => Orange }.
    freeze

def eat(fruit_code)
  fruit_type = FRUIT_TYPES[fruit_code]
end

···

--
Posted via http://www.ruby-forum.com/.

Once you've got the return you can do any substitutions required for
your special name:

cmd = 'fm_shell'
=> "fm_shell"
toolName = cmd[/\A(astro|core|fm_shell|formality|gca_shell|xa)\z/i, 1 ]
=> "fm_shell"
subs = { 'fm' => [ 'fm_shell', 'formality' ], 'gcas' => [ 'gca_shell' ]
}
=> {"fm"=>["fm_shell", "formality"], "gcas"=>["gca_shell"]}
subs.each { |output, input| toolName = output if input.include? toolName
}
=> {"fm"=>["fm_shell", "formality"], "gcas"=>["gca_shell"]}
toolName
=> "fm"

···

--
Posted via http://www.ruby-forum.com/.

Previn,

if you want a flexible solution, I'd go with an hash. Key is the tool
name, value is an array of regexps.

tools = {
    "astro" => [ /astro/ ],
    "fm" => [ /fm_shell/, /formality/ ]
}

You can then iterate over all values, see what matches the string you've
got, and use the key as toolName

HTH.

···

--
Posted via http://www.ruby-forum.com/.

class Tool
   attr_reader :name, :pat

   def initialize name, pat
     @name = name
     @pat = pat
   end

   def === cmd
     @pat === cmd
   end
end

astro = Tool.new 'astro', /^Astro$/
core = Tool.new 'coretools', /^core/
fm = Tool.new 'fm', /^(fm_shell|formality)$/
gcas = Tool.new 'gcas', /^gca_shell$/

tools = [astro, core, fm, gcas]

cmd = "corezap"
puts tools.find {|tool| tool === cmd}.name

cmd = "gca_shell"
case cmd # there is a special relationship between case and #===
when astro; puts "doing astro stuff"
when gcas; puts "doing gcas stuff"
end

···

On 12/20/2013 02:57 AM, Previn Lin wrote:

Is there better way to replace these case statement?

case cmd
           when /^Astro$/
                 toolName = 'astro'

           when /^core/
                 toolName = 'coretools'

           when /^(fm_shell|formality)$/
                 toolName = 'fm'

           when /^gca_shell$/
                 toolName = 'gcas'
     ......

           when /^xa/
                 toolName = 'xa'

           else
                 toolName = ''

end

Dear Joel, Eric, Jason, Joel(VanderWerf),

Thank you so much for your warm help, with your guide, I can use hash
method to replace case statement succesfully.

Yes, as Jason noticed, for this case, reg. needed, and not every reg has
'$' in the end. Also thanks Eric's solution, I know the first time how
to use reg in the hash.

I still not fully understand Joel VanderWerf's method, I'll go on study
it, would you give more help if needed? :slight_smile:

···

--
Posted via http://www.ruby-forum.com/.

Learn about polymorphism.

Henry

···

On 20/12/2013, at 11:57 PM, Previn Lin <lists@ruby-forum.com> wrote:

Is there better way to replace these case statement?

Nice, I'd never used fetch before. That opens up a whole host of
possibilities.

···

--
Posted via http://www.ruby-forum.com/.

Joel Pearson wrote in post #1131246:

Not perfect, but something you could start with:

result = cmd[ /\A(astro|core|fm_shell|formality|gca_shell|xa)\z/i, 1 ]

Hi Joel,

How to go on with this and set toolName accordingly? Could you gic=ve an
example? Thanks.

Previn

···

--
Posted via http://www.ruby-forum.com/\.

BTW the code_book={ Astro: "astro", core: "coretools", fm_shell: "fm", formality: "fm" } works in 2.0 (or 1.9)?

I am new to Ruby, using the latest :slight_smile:

code_book={ Astro: "astro", core: "coretools", fm_shell: "fm", formality: "fm" }

tool_name = code_book[cmd.to_sym]

J.T

···

-----Original Message-----
From: ruby-talk [mailto:ruby-talk-bounces@ruby-lang.org] On Behalf Of Jason Tao
Sent: Friday, December 20, 2013 12:11 PM
To: ruby-talk@ruby-lang.org
Subject: RE: Is there better way to replace these case statement?

cmd="Astro"

#decode
code_book={ Astro: "astro", core: "coretools", fm_shell: "fm", formality: "fm" } tool_name = code_book[cmd.to_sym]

#output
puts tool_name

The downside I see here is it returns nil instead of "" if there is no matching.

J.T

-----Original Message-----
From: ruby-talk [mailto:ruby-talk-bounces@ruby-lang.org] On Behalf Of Previn Lin
Sent: Friday, December 20, 2013 2:58 AM
To: ruby-talk@ruby-lang.org
Subject: Is there better way to replace these case statement?

Is there better way to replace these case statement?

case cmd
          when /^Astro$/
                toolName = 'astro'

          when /^core/
                toolName = 'coretools'

          when /^(fm_shell|formality)$/
                toolName = 'fm'

          when /^gca_shell$/
                toolName = 'gcas'
    ......

          when /^xa/
                toolName = 'xa'

          else
                toolName = ''

end

--
Posted via http://www.ruby-forum.com/.

Previn Lin wrote in post #1131257:

Can we do like the way below? But how to process the Regular express in
our case?

def eat(fruit_code)
  fruit_type =
    case fruit_code
     when 'a'
       Apple
     when 'b'
      Banana
     when 'c'
      Coconut
     when 'o'
      Orange
    end
end

=>

FRUIT_TYPES=
  { 'a' => Apple, 'b' => Banana, 'c' => Coconut, 'o' => Orange }.
    freeze

def eat(fruit_code)
  fruit_type = FRUIT_TYPES[fruit_code]
end

If you want to do this with Regexp here's one option:

types = {
  astro: 'astro',
  core: 'coretools',
  fm_shell: 'fm',
  formality: 'fm',
  gca_shell: 'gcas',
  xa: 'xa'
}
toolName = cmd.match( /\A(#{ types.keys.join('|') })\z/ ) { |s|
types[s.captures.first.to_sym] }

···

--
Posted via http://www.ruby-forum.com/\.

Jason Tao wrote in post #1131307:

tool_name = code_book[cmd.to_sym]

The downside I see here is it returns nil instead of "" if there is no
matching.

There's this option:

tool_name = code_book[cmd.to_sym] || ''

···

--
Posted via http://www.ruby-forum.com/\.

Henry Maddocks wrote in post #1131382:

Learn about polymorphism.

Henry

This is the solution in the book of "Refactoring", but how to implement
it here with regular expression used?

···

--
Posted via http://www.ruby-forum.com/\.

Please do ask. Happy to help...

···

On 12/21/2013 05:13 PM, Previn Lin wrote:

Dear Joel, Eric, Jason, Joel(VanderWerf),

Thank you so much for your warm help, with your guide, I can use hash
method to replace case statement succesfully.

Yes, as Jason noticed, for this case, reg. needed, and not every reg has
'$' in the end. Also thanks Eric's solution, I know the first time how
to use reg in the hash.

I still not fully understand Joel VanderWerf's method, I'll go on study
it, would you give more help if needed? :slight_smile:

Thanks Joel. Just noticed not every reg has '$' in the end. The following code should work the same as the 'case/when':

#the last one is the default
code_book=[ [/^Astro$/, 'Astro'], [/^core/, 'coretools'], [/^(fm_shell|formality)$/, 'fm'], [/^gca_shell$/, 'gcas'], [/^xa/, 'xa'], [/.*/, '']]

cmd=gets.chomp

p code_book.collect { |reg, tool_name| tool_name if cmd =~ reg}.compact.shift

Downside is it will not break after find the first match, bright side is you can catch if multiple matches exist.

J.T

···

-----Original Message-----
From: ruby-talk on behalf of Joel Pearson
Sent: Sat 12/21/2013 8:58 AM
To: ruby-talk@ruby-lang.org
Subject: Re: RE: Is there better way to replace these case statement?

Jason Tao wrote in post #1131307:

tool_name = code_book[cmd.to_sym]

The downside I see here is it returns nil instead of "" if there is no
matching.

There's this option:

tool_name = code_book[cmd.to_sym] || ''

--
Posted via http://www.ruby-forum.com/\.

Can it be more ugly? It is faster though

p code_book[code_book.index {|x| cmd=~x[0]}][1]

J.T

···

-----Original Message-----
From: ruby-talk on behalf of Jason Tao
Sent: Sat 12/21/2013 1:20 PM
To: ruby-talk@ruby-lang.org; ruby-talk@ruby-lang.org
Subject: RE: RE: Is there better way to replace these case statement?

Thanks Joel. Just noticed not every reg has '$' in the end. The following code should work the same as the 'case/when':

#the last one is the default
code_book=[ [/^Astro$/, 'Astro'], [/^core/, 'coretools'], [/^(fm_shell|formality)$/, 'fm'], [/^gca_shell$/, 'gcas'], [/^xa/, 'xa'], [/.*/, '']]

cmd=gets.chomp

p code_book.collect { |reg, tool_name| tool_name if cmd =~ reg}.compact.shift

Downside is it will not break after find the first match, bright side is you can catch if multiple matches exist.

J.T

-----Original Message-----
From: ruby-talk on behalf of Joel Pearson
Sent: Sat 12/21/2013 8:58 AM
To: ruby-talk@ruby-lang.org
Subject: Re: RE: Is there better way to replace these case statement?

Jason Tao wrote in post #1131307:

tool_name = code_book[cmd.to_sym]

The downside I see here is it returns nil instead of "" if there is no
matching.

There's this option:

tool_name = code_book[cmd.to_sym] || ''

--
Posted via http://www.ruby-forum.com/\.

Joel Pearson wrote in post #1131366:

Jason Tao wrote in post #1131307:

tool_name = code_book[cmd.to_sym]

The downside I see here is it returns nil instead of "" if there is no
matching.

There's this option:

tool_name = code_book[cmd.to_sym] || ''

I can't believe I missed this obvious option
Hash.new ''
or
Hash.new { |hash, key| hash[key]='' }

···

--
Posted via http://www.ruby-forum.com/\.