在Ruby中反转字符串的单词?

我试图在Ruby中反转字符串的单词,而不使用反向方法。 我想实现已知的算法:

  • 反转整个字符串
  • 反转反向字符串中的每个单词。

这是我提出的:

class String def custom_reverse(start, limit) i_start = start i_end = limit - 1 while (i_start <= i_end) tmp = self[i_start] self[i_start] = self[i_end] self[i_end] = tmp i_start += 1 i_end -= 1 end return self end def custom_reverse_words self.custom_reverse(0, self.size) i_start = 0 i_end = 0 while (i_end <= self.length) if (i_end == self.length || self[i_end] == ' ') self.custom_reverse(i_start, i_end) i_start += 1 end i_end += 1 end end end test_str = "hello there how are you" p test_str.custom_reverse_words 

但结果是“ yahthello ow ou er ereh

我错过了什么?

任何反向操作的要点是按照您通常所做的相反顺序迭代元素。 也就是说,你通常使用集合(0..N-1)而不是通过(N-1..0)或更具体地说N-1-i,其中i是0..N-1 :

 class String def reverse_words split(/\s+/).map{|w|wl=w.length-1;(0..wl).map{|i|w[wl-i]}.join}.join(' ') end end puts "this is reverse test".reverse_words.inspect # => "siht si esrever tset" 

相同的原理可以应用于给定字符串中的单词。

这种面试问题具有很高的可疑价值。 在生产代码中“聪明”通常是一个非常糟糕的主意。

这是在不使用内置反向的情况下反转数组的一种方法:

 class Array def reverse tmp_ary = self.dup ret_ary = [] self.size.times do ret_ary << tmp_ary.pop end ret_ary end end %w[abc].reverse # => ["c", "b", "a"] 

tmp_ary.pop是秘密。 pop从数组的末尾删除元素。

我能想到的最干净的解决方案是:

 class Array def my_reverse sort_by.with_index {|_, i| -i} end end class String def words split(/\W+/) end def revert_words words.my_reverse.join(' ') end def revert_each_word words.map {|w| w.chars.my_reverse.join}.join(' ') end end 

一旦定义了一个简单有效的arrays反向器:

 def reverse_array(a) (a.length / 2).times {|i| a[i],a[-(i+1)] = a[-(i+1)],a[i]} a end 

你可以非常直接地翻译句子:

 def reverse_sentence(s) reverse_array(s.split('')).join.split(" ").map{|w| reverse_array(w.split('')).join}.join(" ") end reverse_sentence "Howdy pardner" # => "pardner Howdy" 

这是另一种方式:

 class String def reverse_words split.inject([]){|str, word| str.unshift word}.join(' ') end def reverse_chars each_char.inject([]){|str, char| str.unshift char}.join('') end end 

修订

Carey提出了一个好点,reverse_chars可以简化,因为string已经是Enumerable:

 class String def reverse_chars each_char.inject(""){|str, char| str.insert(0, char) } end end