I am trying to find the most efficient way to process lines in a Ruby string in reverse order. These are the two approaches I have:
我正试图找到一种最有效的方法来以反向顺序处理Ruby字符串中的行。我有两种方法:
def double_reverse(lines)
lines.reverse!
lines.each_line do |line|
line.chomp!
line.reverse!
puts line
end
end
def split_and_reverse(lines)
lines.split("\n").reverse.each do |line|
puts line
end
end
if __FILE__ == $0
lines = "This is the first line.\nThis is the second line"
double_reverse(lines)
lines = "This is the first line.\nThis is the second line"
split_and_reverse(lines)
end
I am wondering which one will use less memory. Is there any other approach which will use even less resource? I am primarily concerned about memory usage but if I can reduce the CPU usage too that would be nice.
我在想哪个会用更少的内存。有没有其他的方法可以使用更少的资源?我主要关心内存的使用,但是如果我也能减少CPU的使用,那就太好了。
EDIT 1:
编辑1:
In my use case lines
can have more than a million lines. If split
is going to increase the memory usage by 2x then it is definitely a problem for me. But it may not be a problem if the Ruby VM is smart enough to determine that lines
won't be used after the call to split
and releases it's memory. On the other hand the in-place reverse!
approach theoretically seems to be more efficient since it can be done without making any copy of lines
.
在我的用例中,行可以有超过一百万行。如果split将使内存使用量增加2x,那么对我来说肯定是个问题。但是,如果Ruby VM足够聪明,能够在调用split并释放它的内存之后确定不会使用这些行,那么这可能不是问题。另一方面,原地反转!从理论上讲,方法似乎更有效,因为它可以在不产生任何代码副本的情况下完成。
1 个解决方案
#1
6
Try using Array#reverse_each
:
试着用数组# reverse_each:
lines.split("\n").reverse_each do |line|
puts line
end
Alternatively, if conserving memory is your top priority, then here's a way using String#rindex
with which one can be fairly certain is not doing any extra significant memory allocations beyond the original string:
或者,如果保存内存是您的首选项,那么这里有一种方法使用String#rindex,其中一个可以相当确定的是,它不会在原始字符串之外执行任何额外的重要内存分配:
j = lines.length-1 # lines is the full string, not an array
while -1 <= j
i = lines.rindex("\n", j) || -1
line = lines[i+1..j]
puts line
j = i-1
end
#1
6
Try using Array#reverse_each
:
试着用数组# reverse_each:
lines.split("\n").reverse_each do |line|
puts line
end
Alternatively, if conserving memory is your top priority, then here's a way using String#rindex
with which one can be fairly certain is not doing any extra significant memory allocations beyond the original string:
或者,如果保存内存是您的首选项,那么这里有一种方法使用String#rindex,其中一个可以相当确定的是,它不会在原始字符串之外执行任何额外的重要内存分配:
j = lines.length-1 # lines is the full string, not an array
while -1 <= j
i = lines.rindex("\n", j) || -1
line = lines[i+1..j]
puts line
j = i-1
end