Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Array#reverse.index vs Array#size - Array#index - 1 #28

Closed
wants to merge 1 commit into from
Closed

Adding Array#reverse.index vs Array#size - Array#index - 1 #28

wants to merge 1 commit into from

Conversation

theunraveler
Copy link

The code is a bit uglier and not quite as idiomatic, but I thought the performance improvement may make it work including. The performance gap grows pretty significantly with the size of the array; an array with 100,000,000 items shows the following, for example:

Comparison:
              size -:   233724.3 i/s
     reverse + index:        1.3 i/s - 186342.67x slower

@theunraveler
Copy link
Author

Also note that these two implementations only produce the same result if there is only 1 of the item you're looking for in the array. For example:

>> array = [1, 1, 2, 2, 3, 3, 4, 4]
=> [1, 1, 2, 2, 3, 3, 4, 4]
>> array.reverse.index(3)
=> 2
>> array.size - array.index(3) - 1
=> 3

I'll leave it up to you all whether you'd like to make a note of the difference, or not merge the PR because the examples aren't totally congruous.

@JuanitoFatas
Copy link
Contributor

Hi Jake, as you mentioned, this is not very idiomatic and congruous. But I create a wiki page to document it. Thanks for the pull request, really appreciate it!!! ❤️

Have a nice day!!!

@KaoruDev
Copy link

KaoruDev commented Mar 3, 2015

@theunraveler I'm curious of the use case. I'm not seeing why you would do this I suppose. Mind explaining please?

@theunraveler
Copy link
Author

I just had a rather specific use case in a project I'm working on, actually. I'm writing some automation around naming hardware in a datacenter. The naming is based on the position of the device within its server rack from bottom to top, so I needed to get a list of all hardware in the rack, then sort it by position, then find the index of the hardware in reverse order, and use that index in the hardware name. In the case of a server rack, there are 120 sleds in a typical rack, so I noticed that sleds.reverse.index(sled) was slower than sleds.size - sleds.index(sled) - 1 by a non-trivial amount.

Granted, the use case is not extremely common, and good caching can really make the discrepancy a non-issue, but I just thought it was interesting, so I posted it :-)

@theunraveler theunraveler deleted the array_reverse_index branch March 3, 2015 16:17
@printercu
Copy link

Hi! Do you think this example is really useful? With index(1000) it results in

     reverse + index:   315511.4 i/s
    size - index - 1:   189876.6 i/s - 1.66x slower

@JuanitoFatas I think this example is data specific and can be confusing. And also there is #rindex for this.

@Oppen
Copy link

Oppen commented Feb 1, 2019

Using Array.size - ARRAY.rindex - 1 should actually retain the behavior of Array.reverse.index, since the first appearance on the reversed array corresponds to the last appearance in the original one.

@Oppen
Copy link

Oppen commented Feb 1, 2019

Note that which is faster depends on which end of the array is nearest. If you know there's only a single element or you just care about the index of any matching element, you can use index if you expect the element to be near the beginning of the array.

#!/usr/bin/env ruby

require 'benchmark/ips'

ARRAY = [*1..1000]

def slow(e)
  ARRAY.reverse.index(e)
end

def fast(e)
  ARRAY.size - ARRAY.rindex(e) - 1
end

def faster(e)
  ARRAY.size - ARRAY.index(e) - 1
end

Benchmark.ips do |x|
  x.report('500 - reverse + index') { slow 500 }
  x.report('500 - size - rindex - 1')  { fast 500 }
  x.report('500 - size - index - 1')  { faster 500 }
  x.compare!
end

Benchmark.ips do |x|
  x.report('50 - reverse + index') { slow 50 }
  x.report('50 - size - rindex - 1')  { fast 50 }
  x.report('50 - size - index - 1')  { faster 50 }
  x.compare!
end

Benchmark.ips do |x|
  x.report('950 - reverse + index') { slow 950 }
  x.report('950 - size - rindex - 1')  { fast 950 }
  x.report('950 - size - index - 1')  { faster 950 }
  x.compare!
end
Calculating -------------------------------------
500 - reverse + index
                         31019 i/100ms
500 - size - rindex - 1
                         40222 i/100ms
500 - size - index - 1
                         42217 i/100ms
-------------------------------------------------
500 - reverse + index
                       339223.1 (±5.8%) i/s -    1706045 in   5.047903s
500 - size - rindex - 1
                       493997.5 (±3.2%) i/s -    2493764 in   5.053688s
500 - size - index - 1
                       503386.7 (±2.9%) i/s -    2533020 in   5.036366s

Comparison:
500 - size - index - 1:   503386.7 i/s
500 - size - rindex - 1:   493997.5 i/s - 1.02x slower
500 - reverse + index:   339223.1 i/s - 1.48x slower

Calculating -------------------------------------
50 - reverse + index     20669 i/100ms
50 - size - rindex - 1
                         25936 i/100ms
50 - size - index - 1
                        177229 i/100ms
-------------------------------------------------
50 - reverse + index   224896.8 (±1.5%) i/s -    1136795 in   5.056018s
50 - size - rindex - 1
                       273755.3 (±1.0%) i/s -    1374608 in   5.021783s
50 - size - index - 1
                      3361993.2 (±2.7%) i/s -   16836755 in   5.011957s

Comparison:
50 - size - index - 1:  3361993.2 i/s
50 - size - rindex - 1:   273755.3 i/s - 12.28x slower
50 - reverse + index:   224896.8 i/s - 14.95x slower

Calculating -------------------------------------
950 - reverse + index
                         67432 i/100ms
950 - size - rindex - 1
                        177032 i/100ms
950 - size - index - 1
                         26109 i/100ms
-------------------------------------------------
950 - reverse + index
                       914527.6 (±3.3%) i/s -    4585376 in   5.019921s
950 - size - rindex - 1
                      3344785.2 (±2.3%) i/s -   16818040 in   5.030894s
950 - size - index - 1
                       260991.6 (±3.2%) i/s -    1305450 in   5.007125s

Comparison:
950 - size - rindex - 1:  3344785.2 i/s
950 - reverse + index:   914527.6 i/s - 3.66x slower
950 - size - index - 1:   260991.6 i/s - 12.82x slower

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants