Ruby .reject!vs .delete_if

log*_*son 22 ruby arrays syntax hash

作为Ruby的新手,我对.reject之间的区别有疑问!和.delete_if处理哈希和数组时的方法.如果只是想摆脱某些对象,那么这些方法之间是否存在功能上的差异?有理由使用一个而不是另一个吗?

谢谢!

编辑 我已阅读文档...我想我应该在原来的问题中更清楚.我想知道更多关于效率的差异.他们删除项目的方式有何不同?(再次,忽略返回值.我明白这是一个区别.谢谢!)

Now*_*ker 40

  • reject - 创建一个没有匹配的元素的新数组并返回新数组
  • delete_if- 删除与当前数组匹配的元素并返回该数组
  • reject!- 删除与当前数组匹配的元素.如果某些内容被拒绝,或者nil什么都没有,则返回数组.

  • 感谢您的有组织的回答。它比解析其他人以内联方式编写的内容容易得多。 (2认同)

Exp*_*lls 16

文档非常明确.

不同之处在于,如果reject!不更改数组,则返回nil. delete_if将返回未更改的数组.

  • 哎呀,误读.删除我的答案并提升你的答案.另外,在jRuby 1.7.3中测试(`["a"].delete_if {false}`返回数组,而`["a"].reject!{false}`返回`nil`) (2认同)
  • @user1934428你可能误读了;我说 _if_ `reject!` 不会更改数组...尝试 `a=[1,2,3,4]; a.拒绝!{|我| 我 == 5 };` (2认同)

dim*_*mid 5

tl;dr:delete_if似乎稍微快一点。但是,正如其他答案中所指出的,选择方法的主要考虑因素是返回值的差异。

既然你澄清了你的问题是关于效率的,我做了一些测试:

> time { (1..100000).to_a.reject!{ |n| n % 5 == 0 } }
  0.390000   0.000000   0.390000 (  0.394596)
> time { (1..100000).to_a.delete_if{ |n| n % 5 == 0 } }
  0.400000   0.000000   0.400000 (  0.399122)

> time { (1..200000).to_a.reject!{ |n| n % 5 == 0 } }
  1.650000   0.000000   1.650000 (  1.657927)
> time { (1..200000).to_a.delete_if{ |n| n % 5 == 0 } }
  1.630000   0.010000   1.640000 (  1.637719)

> time { (1..300000).to_a.reject!{ |n| n % 5 == 0 } }
  3.700000   0.000000   3.700000 (  3.717206)
> time { (1..300000).to_a.delete_if{ |n| n % 5 == 0 } }
  3.660000   0.000000   3.660000 (  3.686213)

> time { (1..400000).to_a.reject!{ |n| n % 5 == 0 } }
  7.320000   0.020000   7.340000 (  7.361767)
> time { (1..400000).to_a.delete_if{ |n| n % 5 == 0 } }
  7.190000   0.020000   7.210000 (  7.239549)
Run Code Online (Sandbox Code Playgroud)

所以,看起来超过一定大小delete_if会稍微快一些。 time定义为:

def time(&block)
  puts Benchmark.measure(&block)
end
Run Code Online (Sandbox Code Playgroud)

这些数字分别代表用户 CPU 时间、系统 CPU 时间、用户和系统 CPU 时间的总和以及经过的实时时间。您可以在此处找到对它们含义的解释。请注意,就像在每个基准测试中一样,YMMV,您应该测试您的特定工作流程,而不是我人为的删除 5 倍数数字的示例。