سؤال

Here is my script

require 'benchmark'
require 'ostruct'

Benchmark.bmbm do |x|
  n=10000
  array = n.times.map{ |i| OpenStruct.new id: i }
  hash = Hash[*(array.map{ |s| [s.id, s] }.flatten)]

  x.report('array') do
    array.find{ |s| s.id == 100}
  end
  x.report('hash') do
    hash[100]
  end
end

why with n=100000 I get:

stack level too deep (SystemStackError)

?

not related, but, am I building the hash in the best way?

هل كانت مفيدة؟

المحلول

You’re passing tens of thousands of arguments to a method and that’s just too many for Ruby to handle, causing a stack error.

Instead just pass the un-flattened, un-splatted mapped array to Hash.[], since it accepts that just fine and gives the same (correct) result (without a SystemStackError):

Hash[array.map { |s| [s.id, s] }]

As an aside, we can see the argument count is in fact the issue (rather than specifically Hash.[]) with a simple test:

def f(*args); end
f(*(1..1000000).to_a)  #<SystemStackError: stack level too deep>
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top