【问题标题】:Why is there no `Enumerable#map(sym)` while there is `Enumerable#inject(sym)`?为什么有 `Enumerable#inject(sym)` 却没有 `Enumerable#map(sym)`?
【发布时间】:2015-11-21 14:27:15
【问题描述】:

为什么Enumerable#map 只支持块,而Enumerable#inject 支持其他类型,例如符号?

我希望以下工作

["1", "2"].map(:to_i).inject(:+)

但只有以下有效

["1", "2"].map(&:to_i).inject(:+)

尽管如此,同时使用& 也适用于这两项工作

["1", "2"].map(&:to_i).inject(&:+)

哪一个是最佳实践,为什么?

【问题讨论】:

  • 嗯,这看起来像重复
  • 找不到好的帖子(我记得在这里看到过),但简短的回答是(IIRC):因为它是这样实现的。
  • 如果两种方法都排除符号或仅块,会更一致,不是吗?我认为 ruby​​ 是超级一致的 :-)
  • 哦,但是与 PHP 相比,它是一致性的顶峰。 :)
  • 如果你讨厌我的答案,我会删除它。

标签: ruby symbols proc enumerable


【解决方案1】:

inject 查看是否给出了块,如果没有,它使用符号参数而不是块。对于map,这是无法做到的,因为map 的用法没有块,它返回一个枚举器。

作为 Sergio cmets,map 原则上可以查找参数(而不是查找块或除了查找块之外)。问题是由于 C ruby​​ 选择的特定实现。我怀疑它是这样实现的,因为检查块的存在比检查参数的数量和类要快得多。

没有理由你不应该使用

["1", "2"].map(&:to_i).inject(:+)

为什么不使用方便的符号参数?

【讨论】:

  • 但是map 可以接受一个参数,一个符号。
  • @SergioTulentsev 没错,原则上可以这样做。问题是由于 C ruby​​ 选择的特定实现。参照。 sepp2k 的评论here。我怀疑这是因为检查块比检查参数的数量和类别要快得多。
  • “没有理由你不应该使用” - 但是一致性怎么样,并且不必花费 任何 脑力 CPU 周期来记住此方法是否接受裸符号或不?只需使用&:everythere 就可以了 :)
【解决方案2】:

只需检查Enumerable docs

map { |obj| block } → array
map → an_enumerator

和

inject(initial, sym) → obj
inject(sym) → obj
inject(initial) { |memo, obj| block } → obj
inject { |memo, obj| block } → obj

这两个用哪一个

["1", "2"].map(&:to_i).inject(:+)
["1", "2"].map(&:to_i).inject(&:+)

由你决定,但我很快检查了性能,inject with symbol 似乎工作得更快:

require 'benchmark'

Benchmark.bm do |x|
  x.report { ([1]*1_000_000).map(&:to_i).inject(:+) }
  x.report { ([1]*1_000_000).map(&:to_i).inject(&:+) }
end

    user     system      total        real
0.120000   0.010000   0.130000 (  0.122907)
0.140000   0.000000   0.140000 (  0.146640)

【讨论】:

  • 您似乎在回答第二部分(更好),而不是第一部分(为什么会这样)。你应该澄清这一点。 :)
  • @SergioTulentsev 我无法解释为什么符号参数没有为 map 实现不幸:)
  • 我的意思是,澄清你正在回答后半部分:)
猜你喜欢
  • 2012-04-01
  • 2014-04-26
  • 2019-09-16
  • 1970-01-01
  • 1970-01-01
  • 2016-09-29
  • 2015-05-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多