性能
Performance/AncestorsInclude
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
待定 |
否 |
始终(不安全) |
1.7 |
- |
识别 ancestors.include? 的用法,并将其更改为使用 ⇐。
性能/ArraySemiInfiniteRangeSlice
| 所需 Ruby 版本:2.7 |
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
已禁用 |
否 |
始终(不安全) |
1.9 |
- |
识别使用半无限范围对数组进行切片的地方,这些地方可以用 Array#take 和 Array#drop 代替。此规则是由于微基准测试中的错误而创建的,因此默认情况下已禁用。请参考 https://github.com/rubocop/rubocop-performance/pull/175#issuecomment-731892717
性能/BigDecimalWithNumericArgument
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
待定 |
是 |
始终 |
1.7 |
- |
识别将数值参数传递给 BigDecimal 的地方,这些地方应该将数值参数转换为字符串。从字符串初始化 BigDecimal 比从数值初始化更快。
性能/BindCall
| 所需 Ruby 版本:2.7 |
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
已启用 |
是 |
始终 |
1.6 |
- |
在 Ruby 2.7 中,添加了 UnboundMethod#bind_call。
此规则识别可以将 bind(obj).call(args, …) 替换为 bind_call(obj, args, …) 的地方。
bind_call(obj, args, …) 方法比 bind(obj).call(args, …) 更快。
性能/BlockGivenWithExplicitBlock
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
待定 |
是 |
始终 |
1.9 |
- |
识别在显式检查块参数足以的情况下,不必要地使用 block_given? 的地方。
性能/CaseWhenSplat
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
已禁用 |
是 |
始终(不安全) |
0.34 |
1.13 |
将带有 splat 的 when 条件重新排序到 when 分支的末尾可以提高性能。
每次运行case when语句时,Ruby 都需要为 splat 展开分配内存。由于 Ruby 不像其他一些语言那样支持case when内部的穿透,因此when分支的顺序无关紧要。通过将任何 splat 展开放在when分支列表的末尾,我们将减少为展开分配内存的次数。唯一的例外是,如果您的多个when条件对于任何给定条件都可能为真。这种情况很可能是在定义一个更高层次的 when 条件来覆盖 splat 展开内部的条件。
安全
此 cop 不是不安全的自动更正,因为它不是保证的性能改进。如果case条件处理的数据以有利于命中 splat 展开中的条件的方式进行规范化,则将 splat 条件移到末尾可能会使用更多内存,并且运行速度略慢。有关更多详细信息,请参阅:https://github.com/rubocop/rubocop/pull/6163
Performance/Casecmp
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
已禁用 |
否 |
始终(不安全) |
0.36 |
1.21 |
识别可以使用casecmp更好地实现不区分大小写字符串比较的地方。
此 cop 默认情况下处于禁用状态,因为String#casecmp仅适用于 ASCII 字符。请参阅 https://github.com/rubocop/rubocop/issues/9753.
如果您只使用 ASCII 字符,则可以安全地启用此 cop。
Performance/ChainArrayAllocation
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
已禁用 |
是 |
否 |
0.59 |
- |
识别array.compact.flatten.map { |x| x.downcase }的使用情况。这些方法中的每一个(compact、flatten、map)都会生成一个新的中间数组,该数组会立即被丢弃。相反,当我们知道它是安全的时,更快地进行变异。
性能/CollectionLiteralInLoop
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
待定 |
是 |
否 |
1.8 |
- |
识别在循环中使用数组和哈希字面量的地方。最好将它们提取到局部变量或常量中,以避免在每次迭代时进行不必要的分配。
您可以使用 MinSize 设置要考虑违规的最小元素数量。
性能/CompareWithBlock
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
已启用 |
是 |
始终 |
0.46 |
- |
识别可以将 sort { |a, b| a.foo <⇒ b.foo } 替换为 sort_by(&:foo) 的地方。此 cop 还检查 sort!、min、max 和 minmax 方法。
示例
# bad
array.sort { |a, b| a.foo <=> b.foo }
array.sort! { |a, b| a.foo <=> b.foo }
array.max { |a, b| a.foo <=> b.foo }
array.min { |a, b| a.foo <=> b.foo }
array.minmax { |a, b| a.foo <=> b.foo }
array.sort { |a, b| a[:foo] <=> b[:foo] }
# good
array.sort_by(&:foo)
array.sort_by!(&:foo)
array.sort_by { |v| v.foo }
array.sort_by do |var|
var.foo
end
array.max_by(&:foo)
array.min_by(&:foo)
array.minmax_by(&:foo)
array.sort_by { |a| a[:foo] }
性能/ConcurrentMonotonicTime
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
待定 |
是 |
始终 |
1.12 |
- |
识别可以将 Concurrent.monotonic_time 替换为 Process.clock_gettime(Process::CLOCK_MONOTONIC) 的地方。
性能/ConstantRegexp
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
待定 |
是 |
始终 |
1.9 |
1.10 |
查找具有动态组件的正则表达式,这些组件都是常量。
每次执行包含此类正则表达式的代码时,Ruby 都会分配一个新的 Regexp 对象。将其提取到常量中、对其进行记忆或添加 /o 选项以仅执行一次 #{} 插值并重用该 Regexp 对象会更有效。
示例
# bad
def tokens(pattern)
pattern.scan(TOKEN).reject { |token| token.match?(/\A#{SEPARATORS}\Z/) }
end
# good
ALL_SEPARATORS = /\A#{SEPARATORS}\Z/
def tokens(pattern)
pattern.scan(TOKEN).reject { |token| token.match?(ALL_SEPARATORS) }
end
# good
def tokens(pattern)
pattern.scan(TOKEN).reject { |token| token.match?(/\A#{SEPARATORS}\Z/o) }
end
# good
def separators
@separators ||= /\A#{SEPARATORS}\Z/
end
性能/Count
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
已启用 |
是 |
始终(不安全) |
0.31 |
1.8 |
识别对 Enumerable 上的 count 的使用,这些使用遵循对 select、find_all、filter 或 reject 的调用。查询逻辑可以改为传递到 count 调用中。
安全
此 cop 不安全,因为它与 ActiveRecord 和其他框架存在已知的兼容性问题。在 Rails 5.1 之前,ActiveRecord 会忽略传递给 count 的块。其他方法(如 select)会将关联转换为数组,然后在数组上运行块。使 count 与块一起工作的简单解决方法是调用 to_a.count {…}。
例如
`Model.where(id: [1, 2, 3]).select { |m| m.method == true }.size`
变成
`Model.where(id: [1, 2, 3]).to_a.count { |m| m.method == true }`
示例
# bad
[1, 2, 3].select { |e| e > 2 }.size
[1, 2, 3].reject { |e| e > 2 }.size
[1, 2, 3].select { |e| e > 2 }.length
[1, 2, 3].reject { |e| e > 2 }.length
[1, 2, 3].select { |e| e > 2 }.count { |e| e.odd? }
[1, 2, 3].reject { |e| e > 2 }.count { |e| e.even? }
array.select(&:value).count
# good
[1, 2, 3].count { |e| e > 2 }
[1, 2, 3].count { |e| e < 2 }
[1, 2, 3].count { |e| e > 2 && e.odd? }
[1, 2, 3].count { |e| e < 2 && e.even? }
Model.select('field AS field_one').count
Model.select(:value).count
性能/DeletePrefix
| 所需的 Ruby 版本:2.5 |
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
已启用 |
否 |
始终(不安全) |
1.6 |
1.11 |
在 Ruby 2.5 中,添加了 String#delete_prefix。
此代码检查器识别可以将 gsub(/\Aprefix/, '') 和 sub(/\Aprefix/, '') 替换为 delete_prefix('prefix') 的地方。
此代码检查器具有 SafeMultiline 配置选项,默认情况下为 true,因为 ^prefix 不安全,因为它对于接收者是多行字符串时,其行为将与 delete_prefix 不兼容。
delete_prefix('prefix') 方法比 gsub(/\Aprefix/, '') 更快。
性能/DeleteSuffix
| 所需的 Ruby 版本:2.5 |
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
已启用 |
否 |
始终(不安全) |
1.6 |
1.11 |
在 Ruby 2.5 中,添加了 String#delete_suffix。
此代码检查器识别可以将 gsub(/suffix\z/, '') 和 sub(/suffix\z/, '') 替换为 delete_suffix('suffix') 的地方。
此代码检查器具有 SafeMultiline 配置选项,默认情况下为 true,因为 suffix$ 不安全,因为它对于接收者是多行字符串时,其行为将与 delete_suffix? 不兼容。
delete_suffix('suffix') 方法比 gsub(/suffix\z/, '') 更快。
性能/Detect
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
已启用 |
是 |
始终(不安全) |
0.30 |
1.8 |
识别 first、last、[0] 或 [-1] 连接到 select、find_all 或 filter 的用法,并将它们更改为使用 detect。
示例
# bad
[].select { |item| true }.first
[].select { |item| true }.last
[].find_all { |item| true }.first
[].find_all { |item| true }.last
[].filter { |item| true }.first
[].filter { |item| true }.last
[].filter { |item| true }[0]
[].filter { |item| true }[-1]
# good
[].detect { |item| true }
[].reverse.detect { |item| true }
性能/DoubleStartEndWith
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
已启用 |
是 |
始终 |
0.36 |
0.48 |
检查由 || 分隔的两次 #start_with? 或 #end_with? 调用。在某些情况下,此类调用可以用单个 #start_with?/#end_with? 调用替换。
IncludeActiveSupportAliases 配置选项用于检查 starts_with? 和 ends_with?。这些方法由 Active Support 定义。
示例
# bad
str.start_with?("a") || str.start_with?(Some::CONST)
str.start_with?("a", "b") || str.start_with?("c")
str.end_with?(var1) || str.end_with?(var2)
# good
str.start_with?("a", Some::CONST)
str.start_with?("a", "b", "c")
str.end_with?(var1, var2)
性能/EndWith
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
已启用 |
是 |
始终(不安全) |
0.36 |
1.10 |
识别不必要地使用正则表达式的情况,而 String#end_with? 就足够了。
此 cop 具有 SafeMultiline 配置选项,默认情况下为 true,因为 end$ 不安全,因为它在接收者为多行字符串时将与 end_with? 的行为不兼容。
性能/FixedSize
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
已启用 |
是 |
否 |
0.35 |
- |
不要计算静态大小对象的尺寸。
示例
# String methods
# bad
'foo'.size
%q[bar].count
%(qux).length
# Symbol methods
# bad
:fred.size
:'baz'.length
# Array methods
# bad
[1, 2, thud].count
%W(1, 2, bar).size
# Hash methods
# bad
{ a: corge, b: grault }.length
# good
foo.size
bar.count
qux.length
# good
:"#{fred}".size
CONST = :baz.length
# good
[1, 2, *thud].count
garply = [1, 2, 3]
garply.size
# good
{ a: corge, **grault }.length
waldo = { a: corge, b: grault }
waldo.size
性能/FlatMap
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
已启用 |
是 |
始终 |
0.30 |
- |
识别 map { … }.flatten 的用法,并将其更改为使用 flat_map { … }。
性能/低效哈希搜索
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
已启用 |
否 |
始终(不安全) |
0.56 |
- |
检查哈希中对键和值的低效搜索。
Hash#keys.include? 比 Hash#key? 效率低,因为前者会分配一个新的数组,然后对该数组进行 O(n) 搜索,而 Hash#key? 不会分配任何数组,并执行更快的 O(1) 键搜索。
Hash#values.include? 比 Hash#value? 效率低。虽然它们都对所有值执行 O(n) 搜索,但调用 values 会分配一个新的数组,而使用 value? 则不会。
示例
# bad
{ a: 1, b: 2 }.keys.include?(:a)
{ a: 1, b: 2 }.keys.include?(:z)
h = { a: 1, b: 2 }; h.keys.include?(100)
# good
{ a: 1, b: 2 }.key?(:a)
{ a: 1, b: 2 }.has_key?(:z)
h = { a: 1, b: 2 }; h.key?(100)
# bad
{ a: 1, b: 2 }.values.include?(2)
{ a: 1, b: 2 }.values.include?('garbage')
h = { a: 1, b: 2 }; h.values.include?(nil)
# good
{ a: 1, b: 2 }.value?(2)
{ a: 1, b: 2 }.has_value?('garbage')
h = { a: 1, b: 2 }; h.value?(nil)
性能/IoReadlines
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
已禁用 |
是 |
始终 |
1.7 |
- |
识别可以将低效的 readlines 方法替换为 each_line 的位置,以避免将整个文件内容加载到内存中。
示例
# bad
File.readlines('testfile').each { |l| puts l }
IO.readlines('testfile', chomp: true).each { |l| puts l }
conn.readlines(10).map { |l| l.size }
file.readlines.find { |l| l.start_with?('#') }
file.readlines.each { |l| puts l }
# good
File.open('testfile', 'r').each_line { |l| puts l }
IO.open('testfile').each_line(chomp: true) { |l| puts l }
conn.each_line(10).map { |l| l.size }
file.each_line.find { |l| l.start_with?('#') }
file.each_line { |l| puts l }
性能/MapCompact
| 所需 Ruby 版本:2.7 |
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
待定 |
是 |
始终(不安全) |
1.11 |
- |
在 Ruby 2.7 中,添加了 Enumerable#filter_map。
此检查器识别可以将 map { … }.compact 替换为 filter_map 的位置。
[true, false, nil].compact #=> [true, false]
[true, false, nil].filter_map(&:itself) #=> [true]
性能/MapMethodChain
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
待定 |
否 |
否 |
1.19 |
- |
检查 map 方法是否在链中使用。
不支持自动更正,因为无法自动确定合适的块变量名。
class X
def initialize
@@num = 0
end
def foo
@@num += 1
self
end
def bar
@@num * 2
end
end
[X.new, X.new].map(&:foo).map(&:bar) # => [4, 4]
[X.new, X.new].map { |x| x.foo.bar } # => [2, 4]
性能/MethodObjectAsBlock
性能/OpenStruct
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
已禁用 |
否 |
否 |
0.61 |
- |
检查 OpenStruct.new 调用。OpenStruct 的实例化会使 Ruby 全局方法缓存失效,因为它会导致程序运行时动态方法定义。这可能会影响性能,尤其是在具有多个 OpenStruct 实例化的单线程应用程序中。
性能/范围包含
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
已启用 |
否 |
始终(不安全) |
0.36 |
1.7 |
识别 Range#include? 和 Range#member? 的使用,它们会遍历 Range 中的每个项目以查看指定项目是否存在。相比之下,Range#cover? 只需将目标项目与 Range 的起点和终点进行比较。在绝大多数情况下,这就是我们想要的。
安全
此代码不安全,因为 Range#include?(或 Range#member?)和 Range#cover? 的行为不等效。Range#cover? 可能无法提供预期结果的示例。
('a'..'z').cover?('yellow') # => true
性能/冗余块调用
性能/冗余相等比较块
| 所需的 Ruby 版本:2.5 |
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
待定 |
否 |
始终(不安全) |
1.10 |
- |
检查 Enumerable#all?、Enumerable#any?、Enumerable#one? 和 Enumerable#none? 的使用是否在块中与 === 或类似方法进行比较。
默认情况下,Object#=== 的行为与 Object#== 相同,但这种行为在子类中被适当地重写。例如,当参数在范围内时,Range#=== 返回 true。
此代码具有 AllowRegexpMatch 选项,默认情况下为 true,因为 regexp.match?('string') 通常在块中使用,会导致相反的结果。
[/pattern/].all? { |regexp| regexp.match?('pattern') } # => true
[/pattern/].all? { |regexp| regexp =~ 'pattern' } # => true
[/pattern/].all?('pattern') # => false
示例
# bad
items.all? { |item| pattern === item }
items.all? { |item| item == other }
items.all? { |item| item.is_a?(Klass) }
items.all? { |item| item.kind_of?(Klass) }
# good
items.all?(pattern)
items.all?(Klass)
性能/冗余合并
性能/冗余字符串字符
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
待定 |
是 |
始终 |
1.7 |
- |
检查冗余的String#chars。
示例
# bad
str.chars[0..2]
str.chars.slice(0..2)
str.chars.last
# good
str[0..2].chars
# bad
str.chars.first
str.chars.first(2)
# good
str[0]
str[0...2].chars
str[-1]
# bad
str.chars.take(2)
str.chars.length
str.chars.size
str.chars.empty?
# good
str[0...2].chars
str.length
str.size
str.empty?
# For example, if the receiver is an empty string, it will be incompatible.
# If a negative value is specified for the receiver, `nil` is returned.
str.chars.last(2) # Incompatible with `str[-2..-1].chars`.
str.chars.drop(2) # Incompatible with `str[2..-1].chars`.
性能/正则表达式匹配
| 所需的 Ruby 版本:2.4 |
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
已启用 |
是 |
始终 |
0.47 |
- |
在 Ruby 2.4 中,添加了String#match?、Regexp#match?和Symbol#match?。这些方法比match更快。因为这些方法避免创建MatchData对象或保存反向引用。因此,当不使用MatchData时,请使用match?而不是match。
示例
# bad
def foo
if x =~ /re/
do_something
end
end
# bad
def foo
if x !~ /re/
do_something
end
end
# bad
def foo
if x.match(/re/)
do_something
end
end
# bad
def foo
if /re/ === x
do_something
end
end
# good
def foo
if x.match?(/re/)
do_something
end
end
# good
def foo
if !x.match?(/re/)
do_something
end
end
# good
def foo
if x =~ /re/
do_something(Regexp.last_match)
end
end
# good
def foo
if x.match(/re/)
do_something($~)
end
end
# good
def foo
if /re/ === x
do_something($~)
end
end
性能/反向枚举
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
已启用 |
是 |
始终 |
0.30 |
- |
识别reverse.each的使用情况,并将其更改为使用reverse_each。
如果使用返回值,则不会检测到它,因为结果将不同。
[1, 2, 3].reverse.each {} #=> [3, 2, 1]
[1, 2, 3].reverse_each {} #=> [1, 2, 3]
性能/Size
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
已启用 |
是 |
始终 |
0.30 |
- |
识别在 Array 和 Hash 上使用 count 的地方,并将它们更改为 size。
待办事项:添加对可能已分配给数组或哈希的变量的更高级检测。
示例
# bad
[1, 2, 3].count
(1..3).to_a.count
Array[*1..3].count
Array(1..3).count
# bad
{a: 1, b: 2, c: 3}.count
[[:foo, :bar], [1, 2]].to_h.count
Hash[*('a'..'z')].count
Hash(key: :value).count
# good
[1, 2, 3].size
(1..3).to_a.size
Array[*1..3].size
Array(1..3).size
# good
{a: 1, b: 2, c: 3}.size
[[:foo, :bar], [1, 2]].to_h.size
Hash[*('a'..'z')].size
Hash(key: :value).size
# good
[1, 2, 3].count { |e| e > 2 }
性能/Squeeze
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
待定 |
是 |
始终 |
1.7 |
- |
识别可以将 gsub(/a+/, 'a') 和 gsub!(/a+/, 'a') 替换为 squeeze('a') 和 squeeze!('a') 的地方。
squeeze('a') 方法比 gsub(/a+/, 'a') 更快。
性能/StartWith
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
已启用 |
是 |
始终(不安全) |
0.36 |
1.10 |
识别不必要使用正则表达式的地方,String#start_with? 就足够了。
此代码检测器具有 SafeMultiline 配置选项,默认情况下为 true,因为 ^start 不安全,因为它在接收者为多行字符串时将与 start_with? 不兼容。
性能/StringIdentifierArgument
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
待定 |
是 |
始终 |
1.13 |
- |
识别可以将字符串标识符参数替换为符号标识符参数的地方。它防止了内部字符串到符号转换的冗余。
此代码检测器针对接受标识符(例如方法名)参数的方法,以下示例是其中的一部分。
示例
# bad
send('do_something')
attr_accessor 'do_something'
instance_variable_get('@ivar')
respond_to?("string_#{interpolation}")
# good
send(:do_something)
attr_accessor :do_something
instance_variable_get(:@ivar)
respond_to?(:"string_#{interpolation}")
# good - these methods don't support namespaced symbols
const_get("#{module_path}::Base")
const_source_location("#{module_path}::Base")
const_defined?("#{module_path}::Base")
性能/字符串替换
性能/求和
| 所需的 Ruby 版本:2.4 |
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
待定 |
是 |
始终(不安全) |
1.8 |
1.13 |
识别可以用Enumerable#sum 方法替换自定义代码来查找某些 Enumerable 对象中元素总和的地方。
安全性
只要显式提供初始值,自动更正就不会有问题。
[1, 2, 3].reduce(4, :+) # => 10
[1, 2, 3].sum(4) # => 10
[].reduce(4, :+) # => 4
[].sum(4) # => 4
这对实现了:+ 方法的非数字类型也适用。
['l', 'o'].reduce('Hel', :+) # => "Hello"
['l', 'o'].sum('Hel') # => "Hello"
但是,当不提供初始值时,Enumerable#reduce 会将第一个枚举的值作为初始值,并依次将所有后续值加到它,而Enumerable#sum 会将初始值设置为0 (Integer),这会导致TypeError。
[].reduce(:+) # => nil
[1, 2, 3].reduce(:+) # => 6
['H', 'e', 'l', 'l', 'o'].reduce(:+) # => "Hello"
[].sum # => 0
[1, 2, 3].sum # => 6
['H', 'e', 'l', 'l', 'o'].sum # => in `+': String can't be coerced into Integer (TypeError)
示例
OnlySumOrWithInitialValue: false (默认)
# bad
[1, 2, 3].inject(:+) # Autocorrections for cases without initial value are unsafe
[1, 2, 3].inject(&:+) # and will only be performed when using the `-A` option.
[1, 2, 3].reduce { |acc, elem| acc + elem } # They can be prohibited completely using `SafeAutoCorrect: true`.
[1, 2, 3].reduce(10, :+)
[1, 2, 3].map { |elem| elem ** 2 }.sum
[1, 2, 3].collect(&:count).sum(10)
# good
[1, 2, 3].sum
[1, 2, 3].sum(10)
[1, 2, 3].sum { |elem| elem ** 2 }
[1, 2, 3].sum(10, &:count)
性能/TimesMap
性能/解冻字符串
| 所需的 Ruby 版本:2.3 |
| 默认启用 | 安全 | 支持自动更正 | 添加版本 | 更改版本 |
|---|---|---|---|---|
已启用 |
是 |
始终(不安全) |
0.50 |
1.9 |
在 Ruby 2.3 或更高版本中,使用一元加运算符解冻字符串字面量,而不是String#dup 和 String.new。一元加运算符比String#dup 快。