我有一个合理大小的数组,
a = ("a".."z").to_a
我希望使用某个默认号码,当用于将值作为索引调用时,它(实际上)始终返回nil
。
a[some_default_index] # => nil
对于固定a
,我可以设置一个等于或大于a
大小的固定数字作为默认数字,但a
会有所不同。
我尝试了Float::NAN
和Float::Infinity
,但没有按照我的意图行事。
a[Float::NAN] # => out of range error
a[Float::Infinity] # => out of range error
我可以使用哪个数字作为索引?
答案 0 :(得分:2)
试试这个
max_index = 2**30 - 1
a[max_index] # => nil
错误消息提供了提示RangeError: bignum too big to convert into `long'
也就是说,索引必须符合Ruby底层机器级表示中的long
值。在32位系统上,在64位系统上为2**31 - 1
和2**63 - 1
。
然而,这些值在Ruby中表示为Fixnum
,所以如果你想利用立即加速的fixnums,最好使用它们的最大值。 Ruby使用标记指针来表示Fixnum
整数,因此它们比原始整数小一点,因此对于32位系统而言2**30 - 1
和对于64位系统而言2**62 - 1
。
答案 1 :(得分:1)
这是@AndrewGrimm的优秀版本answer:
a = ("a".."z").to_a
start = Time.now
largest_correct_index = 1
smallest_incorrect_index = nil
until smallest_incorrect_index == largest_correct_index + 1
if smallest_incorrect_index.nil?
next_number_to_try = largest_correct_index * 1000
else
next_number_to_try = (smallest_incorrect_index + largest_correct_index) / 2 # Geometric mean would be more efficient, but more risky
end
if next_number_to_try <= largest_correct_index ||
smallest_incorrect_index && next_number_to_try >= smallest_incorrect_index
raise "Can't happen case"
end
begin
a[next_number_to_try]
largest_correct_index = next_number_to_try
rescue RangeError
smallest_incorrect_index = next_number_to_try
end
end
finish = Time.now
puts "The largest correct index is #{largest_correct_index}"
puts "The smallest incorrect index is #{smallest_incorrect_index}"
puts "Calculation took #{finish - start} seconds"
在32位Ruby上,它返回2**31-1
:
The largest correct index is 2147483647
The smallest incorrect index is 2147483648
Calculation took 0.0 seconds
在64位Ruby和JRuby上,它返回2**63-1
:
The largest correct index is 9223372036854775807
The smallest incorrect index is 9223372036854775808
Calculation took 0.000250378 seconds
所以看起来@ akuhn的answer在大多数情况下都应该足够好。
根据您的需要,您还可以使用哈希:
a = ('a'..'z').to_a
# ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
h = ('a'..'z').map.with_index { |l, i| [i, l] }.to_h
# {0=>"a", 1=>"b", 2=>"c", 3=>"d", 4=>"e", 5=>"f", 6=>"g", 7=>"h", 8=>"i", 9=>"j", 10=>"k", 11=>"l", 12=>"m", 13=>"n", 14=>"o", 15=>"p", 16=>"q", 17=>"r", 18=>"s", 19=>"t", 20=>"u", 21=>"v", 22=>"w", 23=>"x", 24=>"y", 25=>"z"}
require 'fruity'
compare do
_array { a[rand(26)] }
_hash { h[rand(26)] }
end
它似乎不会对表现产生负面影响:
Running each test 16384 times. Test will take about 1 second.
_array is similar to _hash
所有这些:
h[-1]
h[:default]
h[Float::INFINITY]
h[2**1024-1]
会返回nil
。