Why Array.Reverse_Each Is Faster Than Array.Reverse.Each

Why Array.reverse_each is faster than Array.reverse.each

I would definitely say it has to do with the time associating with creating the reverse array! You've only tried really small arrays (an array with 100 elements is still a small array). If you try with bigger arrays (for instance 10k elements), I think you will really notice the difference.

Why is `str.reverse == str` faster than `str[0] != str[-1]`?

There are two factors in favour of the reverse method:

  • Both String#reverse and String#== are written in pure C instead of ruby. Their inner loop already uses the fact that the length of the string is known, so there are no unnecessarry boundary checks.
  • String#[] however needs to check the string boundaries at every call. Also the main loop is written in ruby thereby being a tad bit slower as well. Also it will always create a new (one character long) string object as well to return which needs to be handled, GCd, etc.

It looks like these two factors have a bigger performance gain than what you get by a better algorithm, but which is done in ruby.

Also note that in your test you are not testing a random string, but a specific one, which is really short as well. If you woud try a larger one, then it is possible that the ruby implementaion will be quicker.

How to iterate through an array starting from the last element? (Ruby)

array.reverse.each { |x| puts x }

Is `map` faster than `each`?

I think yes.

I've tried this test

require "benchmark"

n=10000
arr=Array.new(10000,1)
Benchmark.bm do |x|
#Map
x.report do
n.times do
result = arr.map {|a| a + 2}
end
end

#Each
x.report do
n.times do
result = []
arr.each do |a|
result.push(a + 2)
end
end
end
end

And I got this times

       user     system      total        real
5.790000 0.060000 5.850000 ( 5.846956)
8.210000 0.030000 8.240000 ( 8.233849)

Seems like map it's faster

I saw this video http://confreaks.tv/videos/goruco2015-how-to-performance
she shows many ruby profiles and tools, if you are interested to improve your performance you will find a lot of tips there.

added

This is a crazy behavior for me!

require "benchmark"

n=10000
arr=Array.new(10000,1)
Benchmark.bm do |x|
#Map
x.report do
n.times do
result = arr.map {|a| a + 2}
end
end
#Each and push
x.report do
n.times do
result = []
arr.each do |a|
result.push(a + 2)
end
end
end

#Each and <<
x.report do
n.times do
result = []
arr.each do |a|
result << (a + 2)
end
end
end
end

and the result

       user     system      total        real
5.880000 0.080000 5.960000 ( 5.949504)
8.160000 0.010000 8.170000 ( 8.164736)
6.630000 0.010000 6.640000 ( 6.632686)

is the operator "<<" faster than method push? I didn't expect that, I thought that was a kind of alias.

Decrement loop in Ruby on Rails

Array#reverse_each

Same as Array#each, but traverses self in reverse order.

try the below :

<% @orders.reverse_each do |order| %>
#code
<% end %>

Ruby enumerable reverse detect

Method Array#reverse is O(n) in time and space. As you don't need the whole reversed array, you may use Array#reverse_each, that would be O(1) in space. In practice, that's only relevant for really big arrays.

views.reverse_each.detect { |view| view[:user_id] == 1 }
#=> {:user_id=>1, :viewed_at=>"2012-06-29 17:77:28 -0400"}

Is there a reason that we cannot iterate on reverse Range in ruby?

A range is just that: something defined by its start and end, not by its contents. "Iterating" over a range doesn't really make sense in a general case. Consider, for example, how you would "iterate" over the range produced by two dates. Would you iterate by day? by month? by year? by week? It's not well-defined. IMO, the fact that it's allowed for forward ranges should be viewed as a convenience method only.

If you want to iterate backwards over a range like that, you can always use downto:

$ r = 10..6
=> 10..6

$ (r.first).downto(r.last).each { |i| puts i }
10
9
8
7
6

Here are some more thoughts from others on why it's tough to both allow iteration and consistently deal with reverse-ranges.

Reverse a slice of an array in-place

How about this?

def reverse_slice(l, a, b):
l[a:b] = l[a:b][::-1]

l = list(range(10))
reverse_slice(l, 0, 6) # excludes l[6]
print(l)

Output:

[5, 4, 3, 2, 1, 0, 6, 7, 8, 9]

An alternative with the inbuilt function reversed:

def reverse_func(l, a, b):
l[a:b] = reversed(l[a:b])

In my tests, slicing is faster than using reversed by a factor of 1.2x-1.5x.

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

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


Related Topics



Leave a reply



Submit