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
How to Trigger Mouse Event in Capybara Test
Understand "Current_User" Concept When Creating a Login Session in Ruby
Should Rbenv Be Installed System-Wide, or at a User Level
Testing Rake Task with Rspec with Rails Environment
How to Return a Fixed Length Binary Representation of an Integer in Ruby
How to Join a Table and Count Records in Rails 3
How to Upload a Local File to a Carrierwave Model
Rails Installation Error :The 'Atomic' Native Gem Requires Installed Build Tools
Require File Without Executing Code
Rvm Install 1.9.2 Fails When Running Autoconf
How to Store a Ruby Array into a File
Git Post-Receive Hook Not Running Bundle Install
Undefined Method When Accessing Hash Element
Add Current Time Before Log Message
Detecting Linux Distribution/Platform in Ruby