在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