如何在Ruby中反转字符串?我知道字符串#verse。我有兴趣了解如何用纯Ruby编写它,最好是就地解决方案。
答案 0 :(得分:39)
已经存在一种称为“反向!”的原位反向方法:
$ a = "abc"
$ a.reverse!
$ puts a
cba
如果你想手动试试这个(但它可能不是多字节安全的,例如UTF-8),它会慢一点:
class String
def reverse_inplace!
half_length = self.length / 2
half_length.times {|i| self[i], self[-i-1] = self[-i-1], self[i] }
self
end
end
这将从开头的每个字节开始交换每个字节,直到两个索引在中心相交:
$ a = "abcd"
$ a.reverse_inplace!
$ puts a
dcba
答案 1 :(得分:12)
只是为了讨论,有很多替补,很高兴看到速度/效率有很大差异。我稍微清理了代码,因为显示输出的代码反复反转输出。
# encoding: utf-8
require "benchmark"
reverse_proc = Proc.new { |reverse_me| reverse_me.chars.inject([]){|r,c| r.unshift c}.join }
class String
def reverse # !> method redefined; discarding old reverse
each_char.to_a.reverse.join
end
def reverse! # !> method redefined; discarding old reverse!
replace reverse
end
def reverse_inplace!
half_length = self.length / 2
half_length.times {|i| self[i], self[-i-1] = self[-i-1], self[i] }
end
end
def reverse(a)
(0...(a.length/2)).each {|i| a[i], a[a.length-i-1]=a[a.length-i-1], a[i]}
return a
end
def reverse_string(string) # method reverse_string with parameter 'string'
loop = string.length # int loop is equal to the string's length
word = '' # this is what we will use to output the reversed word
while loop > 0 # while loop is greater than 0, subtract loop by 1 and add the string's index of loop to 'word'
loop -= 1 # subtract 1 from loop
word += string[loop] # add the index with the int loop to word
end # end while loop
return word # return the reversed word
end # end the method
lorum = <<EOT
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent quis magna eu
lacus pulvinar vestibulum ut ac ante. Lorem ipsum dolor sit amet, consectetur
adipiscing elit. Suspendisse et pretium orci. Phasellus congue iaculis
sollicitudin. Morbi in sapien mi, eget faucibus ipsum. Praesent pulvinar nibh
vitae sapien congue scelerisque. Aliquam sed aliquet velit. Praesent vulputate
facilisis dolor id ultricies. Phasellus ipsum justo, eleifend vel pretium nec,
pulvinar a justo. Phasellus erat velit, porta sit amet molestie non,
pellentesque a urna. Etiam at arcu lorem, non gravida leo. Suspendisse eu leo
nibh. Mauris ut diam eu lorem fringilla commodo. Aliquam at augue velit, id
viverra nunc.
EOT
结果:
RUBY_VERSION # => "1.9.2"
name = "Marc-André"; reverse_proc.call(name) # => "érdnA-craM"
name = "Marc-André"; name.reverse! # => "érdnA-craM"
name = "Marc-André"; name.chars.inject([]){|s, c| s.unshift(c)}.join # => "érdnA-craM"
name = "Marc-André"; name.reverse_inplace!; name # => "érdnA-craM"
name = "Marc-André"; reverse(name) # => "érdnA-craM"
name = "Marc-André"; reverse_string(name) # => "érdnA-craM"
n = 5_000
Benchmark.bm(7) do |x|
x.report("1:") { n.times do; reverse_proc.call(lorum); end }
x.report("2:") { n.times do; lorum.reverse!; end }
x.report("3:") { n.times do; lorum.chars.inject([]){|s, c| s.unshift(c)}.join; end }
x.report("4:") { n.times do; lorum.reverse_inplace!; end }
x.report("5:") { n.times do; reverse(lorum); end }
x.report("6:") { n.times do; reverse_string(lorum); end }
end
# >> user system total real
# >> 1: 4.540000 0.000000 4.540000 ( 4.539138)
# >> 2: 2.080000 0.010000 2.090000 ( 2.084456)
# >> 3: 4.530000 0.010000 4.540000 ( 4.532124)
# >> 4: 7.010000 0.000000 7.010000 ( 7.015833)
# >> 5: 5.660000 0.010000 5.670000 ( 5.665812)
# >> 6: 3.990000 0.030000 4.020000 ( 4.021468)
有趣的是,“C”版本(“reverse_string()”)是最快的纯Ruby版本。 #2(“反向!”)是最快的,但它正在利用{C}中的[].reverse
。
添加额外的测试用例(7):
def alt_reverse(string)
word = ""
chars = string.each_char.to_a
chars.size.times{word << chars.pop}
word
end
如果字符串更长(lorum *= 10, n/=10
),我们可以看到差异变宽,因为某些函数在O(n ^ 2)中,而其他函数(我的:-)是O(n):
user system total real
1: 10.500000 0.030000 10.530000 ( 10.524751)
2: 0.960000 0.000000 0.960000 ( 0.954972)
3: 10.630000 0.080000 10.710000 ( 10.721388)
4: 6.210000 0.060000 6.270000 ( 6.277207)
5: 4.210000 0.070000 4.280000 ( 4.268857)
6: 10.470000 3.540000 14.010000 ( 15.012420)
7: 1.600000 0.010000 1.610000 ( 1.601219)
答案 2 :(得分:8)
这是使用inject和unshift执行此操作的一种方法:
"Hello world".chars.inject([]) { |s, c| s.unshift(c) }.join
答案 3 :(得分:7)
内置reverse
的Ruby等价物看起来像:
# 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é"
注意:这假定为Ruby 1.9,或者require "backports"
,并为UTF-8设置$KCODE
。
对于不涉及reverse
的解决方案,可以这样做:
def alt_reverse(string)
word = ""
chars = string.each_char.to_a
chars.size.times{word << chars.pop}
word
end
注意:使用[]
访问单个字母的任何解决方案都是O(n^2)
的顺序;要访问第1000个字母,Ruby必须逐个检查第一个999以检查多字节字符。因此,对each_char
中的解决方案使用像O(n)
这样的迭代器非常重要。
要避免的另一件事是建立增加长度的中间值;在+=
中使用<<
代替alt_reverse
也可以使解O(n^2)
代替O(n)
。
使用unshift
构建数组也会生成解决方案O(n^2)
,因为它意味着每次执行unshift
时重新复制一个索引更高的所有现有元素。
答案 4 :(得分:5)
str = "something"
reverse = ""
str.length.times do |i|
reverse.insert(i, str[-1-i].chr)
end
答案 5 :(得分:4)
"abcde".chars.reduce{|s,c| c + s } # => "edcba"
答案 6 :(得分:3)
使用
def reverse_string(string) # Method reverse_string with parameter 'string'.
loop = string.length # int loop is equal to the string's length.
word = '' # This is what we will use to output the reversed word.
while loop > 0 # while loop is greater than 0, subtract loop by 1 and add the string's index of loop to 'word'.
loop -= 1 # Subtract 1 from loop.
word += string[loop] # Add the index with the int loop to word.
end # End while loop.
return word # Return the reversed word.
end # End the method.
答案 7 :(得分:2)
下面描述的解决方案。没有必要超出数组大小的一半:
module V2
end
答案 8 :(得分:1)
难以阅读单行,
def reverse(a)
(0...(a.length/2)).each {|i| a[i], a[a.length-i-1]=a[a.length-i-1], a[i]}
return a
end
答案 9 :(得分:1)
另外,使用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在这里会很方便,因为你可以嵌套你的反转算法(并且仍然保持一条线)。例如,如果您需要在已经反转的句子中反转每个单词,这将非常方便:
# 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"
答案 10 :(得分:1)
考虑一下Rubinius如何实现该方法 - 它们在Ruby本身中实现了大部分核心库,如果在Ruby中实现String#reverse
和String#reverse!
,我不会感到惊讶。
答案 11 :(得分:1)
这是一个对我来说最有意义的解决方案作为红宝石初学者
def reverse(string)
reversed_string = ''
i = 0
while i < string.length
reversed_string = string[i] + reversed_string
i += 1
end
reversed_string
end
p reverse("helter skelter")
答案 12 :(得分:1)
def palindrome(string)
s = string.gsub(/\W+/,'').downcase
t = s.chars.inject([]){|a,b| a.unshift(b)}.join
return true if(s == t)
false
end
答案 13 :(得分:1)
def reverse(string)
result = ""
idx = string.length - 1
while idx >= 0
result << string [idx]
idx = idx - 1
end
result
end
答案 14 :(得分:0)
n / 2复杂度的简单经典方式
str = "Hello World!";
puts str;
for i in 0..(str.length/2).to_i
mid = (str.length-1-i);
temp = str[i];
str[i] = str[aa];
str[aa] = temp;
end
puts str;
答案 15 :(得分:0)
这是一个简单的替代方案,它首先将字符串分解为数组,计算长度并减去一个(因为ruby的索引规则从0开始的数组),创建一个空变量,然后在键上运行迭代数组,同时将数组长度减去当前数组索引的值附加到创建的空变量,当它到达第0个(对不起我的法语)值时,它会停止。希望这会有所帮助。
class String
def rString
arr = self.split("")
len = arr.count - 1
final = ""
arr.each_index do |i|
final += arr[len - i]
end
final
end
end
答案 16 :(得分:0)
HttpContext.Current.Request.Headers["Origin"].ToString()
答案 17 :(得分:0)
如果你有句“最伟大的胜利就是那个”并且你想拥有“那是胜利最大的”你应该使用这种方法
def solution(sentance)
sentance.split.reverse.join(" ")
end
solution("The greatest victory is that")
答案 18 :(得分:0)
def reverse(string)
reversed_string = ""
idx = 0
while idx < string.length
reversed_string = string[idx] + reversed_string
idx += 1
end
return reversed_string
end
答案 19 :(得分:0)
我相信这也会起作用
def reverse(str)
string = ''
(0..str.size-1).each do |i|
string << str[str.size - 1 - i]
end
string
end
答案 20 :(得分:0)
在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)
答案 21 :(得分:0)
这是使用xor按位运算的替代方法:
class String
def xor_reverse
len = self.length - 1
count = 0
while (count < len)
self[count] ^= self[len]
self[len] ^= self[count]
self[count] ^= self[len]
count += 1
len -= 1
end
self
end
"foobar".xor_reverse
=> raboof