“keys.each”和“each_key”有什么区别?

8
当遍历哈希表时,如下所示:
hash.keys.each do |key|
  process_key(key)
end

Rubocop建议我使用:

each_key

替代:

keys.each

“key”的区别在于,keys.each是对散列的键进行迭代,而each_key则是一个哈希方法,用于迭代哈希表中的键。
2个回答

6
Rubocop希望你根据你的评估代码遵循这个,以获得更好的性能。当使用大量数据时,这一点就会变得明显。这是相关文档:https://github.com/bbatsov/rubocop/blob/master/manual/cops_performance.md#performancehasheachmethods
我还找到了一个人编写的基准测试,用于测试这个问题:https://gist.github.com/jodosha/8ca2bee6137be94e9dcb
我对其进行了一些修改,并在我的一个系统上运行了它:
Warming up --------------------------------------
         string each   128.742k i/100ms
         string keys   114.523k i/100ms
     string each_key   134.279k i/100ms
         symbol each   128.838k i/100ms
         symbol keys   109.398k i/100ms
     symbol each_key   132.021k i/100ms
Calculating -------------------------------------
         string each      2.053M (± 4.0%) i/s -     10.299M in   5.026890s
         string keys      1.864M (± 1.4%) i/s -      9.391M in   5.039759s
     string each_key      2.224M (± 5.5%) i/s -     11.145M in   5.032201s
         symbol each      2.082M (± 1.0%) i/s -     10.436M in   5.013145s
         symbol keys      1.815M (± 2.1%) i/s -      9.080M in   5.004690s
     symbol each_key      2.240M (± 1.9%) i/s -     11.222M in   5.012184s

Comparison:
     symbol each_key:  2239720.0 i/s
     string each_key:  2224205.1 i/s - same-ish: difference falls within error
         symbol each:  2081895.2 i/s - 1.08x  slower
         string each:  2052884.9 i/s - 1.09x  slower
         string keys:  1863740.5 i/s - 1.20x  slower
         symbol keys:  1815131.1 i/s - 1.23x  slower

链式调用方法会比使用内置方法慢(在这种情况下),该内置方法使用单个特殊枚举器完成任务。语言的创建者之所以放置它,是有原因的,而且它是惯用语。


3
Rubocop是错误的。你该使用哪个方法取决于你想要什么返回值。
- 如果你想要一个键的数组,那么你应该使用 `keys.each`。`key` 创建了一个新的键数组,而 `each` 在每个键上执行块后返回该键数组。 - 如果你不需要一个键的数组(并且想要原始哈希表),那么你应该使用 `each_key`,因为它不会创建一个将不会被使用的数组,这样更有效率。

3
应用于海报实现时,Rubocop 并没有错。 - Derek Wright
1
谢谢,讲得非常清楚。 - jStaff
@sawa 在 @ddubs 的回答基础上进行了扩展,each 的返回值没有被使用,因此 keys.each 创建了一个临时数组,然后被丢弃。each_key 创建了一个惰性枚举器,在处理大型哈希表时更加高效。 - Max
问题不在于使用each返回的枚举器,而是不必要地创建了枚举器keys,然后链接到另一个枚举器each的创建。为什么要创建额外的开销,当你可以利用单个特殊目的的枚举器呢?它确实就是为这个精确的原因而存在的! - Derek Wright
@ddubs 不,正如我多次指出的那样,each_key 不会返回键数组,而 keys.each 会。each_key 返回原始哈希表。 - sawa
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接