Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I efficiently processing lines in a string in reverse order in Ruby?

Tags:

string

ruby

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:

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.

EDIT 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.

like image 330
russoue Avatar asked Sep 02 '26 02:09

russoue


1 Answers

Try using Array#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:

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
like image 160
Matt Avatar answered Sep 04 '26 20:09

Matt



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!