如果变量为nil,则赋值字符串,否则附加

时间:2016-08-26 09:05:58

标签: ruby-on-rails ruby

我正在尝试缩短此代码:

if a.nil?
  a = "foo"
else
  a << "foo"
end

anil或字符串。

我已尝试过a ||= "foo"a += "foo",但如果anil,则无效。

4 个答案:

答案 0 :(得分:8)

nil.to_s等于''所以你可以写

a = a.to_s + 'foo'

或另类

a = "#{a}foo"

答案 1 :(得分:5)

这可能与您的情况无关,但a +=a <<之间存在差异。

+=a分配一个新字符串,保留旧字符串不变:

a = 'abc'
b = a

a += 'foo'

a #=> "abcfoo"   # <- a refers to the new string object
b #=> "foo"      # <- b still refers to the original string

这是因为String#+会返回 new 字符串。 a += 'foo'相当于a = a + 'foo'

另一方面

String#<< 修改现有字符串,它不会创建新字符串:

a = 'abc'
b = a

a << 'foo'

a #=> "abcfoo"
b #=> "abcfoo"   # <- both changed, because a and b refer to the same object

因此,为了缩短代码而不改变其行为,您可以使用:

(a ||= '') << 'foo'
如果a ||= ''a

a会为nil分配一个空字符串。然后<< 'foo''foo'追加到a

答案 2 :(得分:0)

写如下:

a = a.nil? ? (a.to_s + 'foo') : 'foo'

答案 3 :(得分:0)

如果您想组合2个字符串(其中任意一个可以为nil),则可以执行以下操作:

a.nil? ? a = (b || '') : a << (b || '')

即使ab或两者均为nil,此方法也有效。

即使语法有些丑陋,这也比替代方法快得多。

基准:

require 'benchmark'

n = 50_000_000
Benchmark.bm do |x|
  x.report("compact.reduce(:+)")   { n.times { a = nil; b = 'foo'; a = [a, b].compact.reduce(:+) } }
  x.report("string interpolation") { n.times { a = nil; b = 'foo'; a = "#{a}#{b}" } }
  x.report("to_s")                 { n.times { a = nil; b = 'foo'; a = a.to_s + b.to_s } }
  x.report("(x || '') +")          { n.times { a = nil; b = 'foo'; a = (a || '') + b } }
  x.report("(x || '') <<")         { n.times { a = nil; b = 'foo'; a = (a || '') << b } } # will throw an exception if used with `frozen_string_literal: true`
  x.report("ternary")              { n.times { a = nil; b = 'foo'; a.nil? ? a = (b || '') : a << (b || '') } }
end

结果:

                      user       system     total       real
compact.reduce(:+)    6.677367   0.000000   6.677367 (  6.677337)
string interpolation  7.983451   0.000000   7.983451 (  7.983440)
to_s                  7.067699   0.000000   7.067699 (  7.067702)
(x || '') +           5.130624   0.000000   5.130624 (  5.130585)
(x || '') <<          4.809965   0.000000   4.809965 (  4.809978)
ternary               3.300871   0.000000   3.300871 (  3.300838)