Muizz Mahdy
Muizz Mahdy

Reputation: 808

Switching words in a string sentence using ruby

I made a program which stores strings of names in an array, it starts by asking for user input using gets.chomp, after typing ADD Name, it adds the name into an array using push, and DEL Name, to delete that name from the array, now i want to enter "REPLACE Name1 Name2" to replace Name1 with Name2 in the array. Thank you in advance :)

class Base
  @@names_array = Array.new(0)

  def set_names_array(name)
  @@names_array.push(name)
  end

  def get_names_array
    return @@names_array
  end

  def delete_name(name)
    @@names_array.delete(name)
  end
end


class Op
  loop_flag = true
  puts "Type ADD 'name' to add a name, DEL 'name' to delete, and EXIT to end program."

  while loop_flag
    command = gets.chomp
    @nameobj = Base.new

    if command[0..2] == "ADD"
      @@name = command[4, command.length]

      @nameobj.set_names_array(@@name)

      puts "#{@@name} was added."
      puts "Names:"
      puts "#{@nameobj.get_names_array}"
    end

    if command == "EXIT"
      puts "Ended."
      loop_flag = false
    end

    if command[0..2] == "DEL"
      for i in @nameobj.get_names_array
        if i == command[4, command.length]
          @nameobj.delete_name(i)
          puts "Names:"
          puts "#{@nameobj.get_names_array}"
        end
      end
    end

    if command[0..2] == "REP"
    # cannot do [4, command.length] because there will be 2 names with
    # various lengths which aren't fixed.
    end

  end
end

Upvotes: 0

Views: 115

Answers (2)

tadman
tadman

Reputation: 211540

There's a lot of things to note here, but the most important is that while you're allowed to put free-form code within class or module definitions in practice that's discouraged except for situations where you've got no other choice, like you're doing some metaprogramming at the class or module level.

In virtually every other case you'll want to express that code either in the main context, that is outside of these definitions, or within well-defined methods you can call as required.

Digging deeper, the Base class you've defined seems to use class-level variables exclusively. This means that all of the objects that new produces are functionally identical even if technically different. What you probably want is a simple singleton version:

module NameRegistry
  def self.names
    @names ||= [ ]
  end
end

Using this is now pretty simple, which I'll demonstrate in a second. The next thing to fix is the parser class by dramatically reducing its responsibility. You can use regular expressions to define a simple grammar that's flexible, and can easily be adapted for more unusual use cases:

class CommandParser
  def parse(line)
    case (line)
    when /\AADD\s+(.*)\z/i
      NameRegistry.names.push($1)
    when /\ADEL\s+(.*)\z/i
      NameRegistry.names.delete($1)
    when /\AREP\s+(.*)\s+WITH\s+(.*)\z/i
      if (NameRegistry.names.delete($1))
        NameRegistry.names.push($2)
      end
    when /\AEXIT\z/i
      # Signal that this command was terminal
      return false
    end

    # Default to success
    true
  end
end

This leads to a chunk of main code that looks like this:

puts "Type ADD 'name' to add a name, DEL 'name' to delete, and EXIT to end program."

parser = CommandParser.new

while (parser.parse(gets.chomp))
  puts "Names: #{NameRegistry.names.join(', ')}"
end

Upvotes: 1

João Marinho
João Marinho

Reputation: 91

You can add this method to Base class:

def replace_names_array(name_to_replace, new_name)
  @@names_array = @@names_array.map do |name|
    name == name_to_replace ? new_name : name
  end
end

Upvotes: 2

Related Questions