Reverse a string in Ruby

前端 未结 22 1045
广开言路
广开言路 2020-12-05 06:36

How do you reverse a string in Ruby? I know about string#reverse. I\'m interested in understanding how to write it in pure Ruby, preferably an in-place solution.

相关标签:
22条回答
  • 2020-12-05 07:20

    The Ruby equivalent of the builtin reverse could look like:

    # encoding: utf-8
    
    class String
      def reverse
        each_char.to_a.reverse.join
      end
    
      def reverse!
        replace reverse
      end
    end
    
    str = "Marc-André"
    str.reverse!
    str # => "érdnA-craM"
    str.reverse # => "Marc-André"
    

    Note: this assumes Ruby 1.9, or else require "backports" and set $KCODE for UTF-8.

    For a solution not involving reverse, one could do:

    def alt_reverse(string)
      word = ""
      chars = string.each_char.to_a
      chars.size.times{word << chars.pop}
      word
    end                        
    

    Note: any solution using [] to access individual letters will be of order O(n^2); to access the 1000th letter, Ruby must go through the first 999 one by one to check for multibyte characters. It is thus important to use an iterator like each_char for a solution in O(n).

    Another thing to avoid is to build intermediate values of increasing length; using += instead of << in alt_reverse would also make the solution O(n^2) instead of O(n).

    Building an array with unshift will also make the solution O(n^2), because it implies recopying all existing elements one index higher each time one does an unshift.

    0 讨论(0)
  • 2020-12-05 07:25

    In Ruby:

    name = "Hello World"; reverse_proc.call(name) 
    
    name = "Hello World"; name.reverse! 
    
    name = "Hello World"; name.chars.inject([]){|s, c| s.unshift(c)}.join 
    
    name = "Hello World"; name.reverse_inplace!; 
    
    name = "Hello World"; reverse(name) 
    
    name = "Hello World"; reverse_string(name) 
    
    0 讨论(0)
  • 2020-12-05 07:26

    The solution described below. There is no need to go beyond the half of array size:

    class ReverseString
    
      def initialize(array)
        @array = array
        @size  = @array.size
      end
    
      def process
        (0...@size/2).to_a.each_with_index do |e,i|
          @array[i], @array[@size-i-1] = @array[@size-i-1], @array[i]
        end
        @array
      end
    
    end
    
    
    require 'minitest/autorun'
    
    class ReverseStringTest < Minitest::Unit::TestCase
      def test_process
        assert_equal "9876543210", ReverseString.new("0123456789").process
      end
    end
    
    0 讨论(0)
  • 2020-12-05 07:26

    Also, using Procs ...

    Proc.new {|reverse_me| reverse_me.chars.inject([]){|r,c| r.unshift c}.join}.call("The house is blue")
    
    => "eulb si esuoh ehT"
    

    Proc.new would be handy here because you could then nest your reversing algorithm (and still keep things on one line). This would be handy if, for instance, you needed to reverse each word in an already-reversed sentence:

    # Define your reversing algorithm
    reverser = Proc.new{|rev_me| rev_me.chars.inject([]){r,c| r.unshift c}.join}
    
    # Run it twice - first on the entire sentence, then on each word
    reverser.call("The house is blue").split.map {|w| reverser.call(w)}.join(' ')
    
    => "blue is house The"
    
    0 讨论(0)
提交回复
热议问题