红宝石中#entry和#to_a之间的区别

时间:2013-12-07 17:20:04

标签: ruby

ruby​​中的#entries模块的#to_aEnumerable方法之间的基本区别是什么。似乎在Hash上返回相同的结果

>> hash = {"name" => "foo" , "age" => "23"}
=> {"name"=>"foo", "age"=>"23"}

>> hash.to_a 
=> [["name","foo"],["age",23]]

>> hash.entries
=> [["name","foo"],["age",23]]

1 个答案:

答案 0 :(得分:15)

这是差异(查看# =>之后的输出):

h = {}
h.method(:entries) # => #<Method: Hash(Enumerable)#entries>
h.method(:to_a) # => #<Method: Hash#to_a>
h.method(:entries).owner # => Enumerable
h.method(:to_a).owner # => Hash

Hash有一个实例方法#to_a,因此它不会调用Enumerable#to_a。但是Hash没有自己的方法#entries,因此它正在调用Enumerable#entries,因为Hash包含Enumerable模块。

Hash.included_modules # => [Enumerable, Kernel]

Enumerable#entriesEnumerable#to_a之间没有区别,据我所知,两者使用TracePoint的工作方式相似:

1. trace = TracePoint.new do |tp|
2.    p [tp.lineno, tp.event, tp.defined_class,tp.method_id]
3. end
4.
5. trace.enable do
6.  (1..2).entries
7.  (1..2).to_a
8. end

# >> [5, :b_call, nil, nil]
# >> [6, :line, nil, nil]
# >> [6, :line, nil, nil]
# >> [6, :c_call, Enumerable, :entries]
# >> [6, :c_call, Range, :each]
# >> [6, :c_return, Range, :each]
# >> [6, :c_return, Enumerable, :entries]
# >> [7, :line, nil, nil]
# >> [7, :line, nil, nil]
# >> [7, :c_call, Enumerable, :to_a]
# >> [7, :c_call, Range, :each]
# >> [7, :c_return, Range, :each]
# >> [7, :c_return, Enumerable, :to_a]
# >> [8, :b_return, nil, nil]

是的,Hash#to_aEnumerable#to_a快。

部分 - 我

require 'benchmark'

class Hash
  remove_method :to_a
end

hsh = Hash[*1..1000]


Benchmark.bm(10) do |b|
  b.report("Enumerable#to_a")    { hsh.to_a }
end
# >>                  user     system      total        real
# >> Enumerable#to_a  0.000000   0.000000   0.000000 (  0.000126)

第二部分

require 'benchmark'

hsh = Hash[*1..1000]


Benchmark.bm(10) do |b|
  b.report("Hash#to_a")    { hsh.to_a }
end
# >>                  user     system      total        real
# >> Hash#to_a     0.000000   0.000000   0.000000 (  0.000095)
相关问题