我们应该在应用delete之前检查字符串中的字符!()?

时间:2017-05-05 17:51:37

标签: ruby

这是相当微不足道的,但已经让我误解了很长一段时间。

我有一个字符串:

x = 'abc/'

并希望删除' /'令牌。

我所知道的最简单的方法是:

x.delete!('/')

工作正常。检查对象ID:

x = 'abc/'
x.object_id     # => 90851540
x.delete!('/')
x.object_id     # => 90851540
x               # => "abc"

对象id保持不变,所以我得出结论 Ruby原样修改了x,没有生成新副本。

检查字符串是否真的有' /'是否更好?首先是人物角色 将delete!()应用于它?

我记得有人曾经说过"没关系" 因为delete!()无论如何都会检查给定的String, 并且只有在字符串中包含字符时才进行修改。

这很公平。

但我想知道两者的利弊 做法。将:

if x.include? '/'

更快?会更好还是更方便?

在代码中它可能更清晰,但它 也使代码更冗长,也许它 也可能导致一些开销。

有时我单独使用delete!(),没有任何检查,有时我会进行检查。

有一种方式比 另外,因为现在我稍微赞成 "没有,如果检查",不是因为速度原因而是在很大程度上 因为语法较少/代码较少。

2 个答案:

答案 0 :(得分:3)

我可能会在没有检查大部分时间的情况下使用delete!(“更少的代码”并且仍然清晰),但我们可以评估性能:

test.rb

require 'benchmark'

iterations = 1_000_000

puts "'/' ALWAYS PRESENT"
Benchmark.bmbm do |bm|
  bm.report('without if') do
    iterations.times do
      x = "abc/"
      x.delete!("/")
    end
  end

  bm.report('with if') do
    iterations.times do
      x = "abc/"
      x.delete!("/") if x.include?("/")
    end
  end
end

puts "\n'/' NEVER PRESENT"
Benchmark.bmbm do |bm|
  bm.report('without if') do
    iterations.times do
      x = "abc"
      x.delete!("/")
    end
  end

  bm.report('with if   ') do
    iterations.times do
      x = "abc"
      x.delete!("/") if x.include?("/")
    end
  end
end

结果

'/' ALWAYS PRESENT
Rehearsal ----------------------------------------------
without if   0.540000   0.000000   0.540000 (  0.541003)
with if      0.630000   0.010000   0.640000 (  0.632728)
------------------------------------- total: 1.180000sec

                 user     system      total        real
without if   0.510000   0.000000   0.510000 (  0.513438)
with if      0.630000   0.000000   0.630000 (  0.632055)

'/' NEVER PRESENT
Rehearsal ----------------------------------------------
without if   0.510000   0.000000   0.510000 (  0.513233)
with if      0.190000   0.000000   0.190000 (  0.194709)
------------------------------------- total: 0.700000sec

                 user     system      total        real
without if   0.510000   0.000000   0.510000 (  0.514632)
with if      0.180000   0.000000   0.180000 (  0.186374)

基于这个结果,我们看到(正如人们所料),删除之前的检查有点慢(由于额外的检查),而不仅仅是删除字符串包含{{1 }}。但是,当/不存在时,首先检查要快得多。

因此,从性能的角度来看,如果您预计没有/的案例比例较高,则可能需要使用include?

如果您想知道 50%/ 50%情景会是什么样子,这就是测试:

test.rb

/

结果

require 'benchmark'

iterations = 500_000

puts "\n'/' PRESENT IN 50%"
Benchmark.bmbm do |bm|
  bm.report('without if') do
    iterations.times do
      x = "abc/"
      x.delete!("/")
    end

    iterations.times do
      x = "abc"
      x.delete!("/")
    end
  end

  bm.report('with if   ') do
    iterations.times do
      x = "abc/"
      x.delete!("/") if x.include?("/")
    end

    iterations.times do
      x = "abc"
      x.delete!("/") if x.include?("/")
    end
  end
end

答案 1 :(得分:1)

我不会检查原因,这是多余的。 即使我检查令牌存在,ruby无论如何都会再次检查它(并且无法跳过它)。 我看到的一个问题是零检查,变量可能是零。在那种情况下,我会做variable.to_s.delete!()之类的事情。 因此,我认为我有足够的理由跳过检查/验证令牌的存在,我没有理由做出防御性编码。