为什么Ruby没有真正的StringBuffer或者StringIO?
我最近读了一篇关于在Ruby中使用StringIO
的好post 。 然而作者没有提到的是, StringIO
只是一个“我”。 没有“O” 你不能这样做,例如:
s = StringIO.new s << 'foo' s << 'bar' s.to_s # => should be "foo\nbar" # => really is ''`
Ruby确实需要一个StringBuffer,就像Java一样。 StringBuffers有两个重要的用途。 首先,他们让你testing一下Ruby的StringIO的输出结果。 其次,它们对于从小部件中构build长弦是有用的 – Joel一再提醒我们的事情是非常缓慢的。
有没有好的替代品?
Ruby中的string是可变的,但这并不意味着我们应该总是依赖于这个function。 如果stuff
很大,那么这个性能和内存要求就非常糟糕。
result = stuff.map(&:to_s).join(' ')
在Java中这样做的“正确”方式是:
result = StringBuffer.new("") for(String s : stuff) { result.append(s); }
虽然我的Java有点生疏。
我看了看StringIO
的ruby文档,看起来像你想要的是StringIO#string
,而不是StringIO#to_s
因此,将您的代码更改为:
s = StringIO.new s << 'foo' s << 'bar' s.string
像Ruby中的其他IOtypes的对象一样,当你写入一个IO时,字符指针前进。
>> s = StringIO.new => #<StringIO:0x3659d4> >> s << 'foo' => #<StringIO:0x3659d4> >> s << 'bar' => #<StringIO:0x3659d4> >> s.pos => 6 >> s.rewind => 0 >> s.read => "foobar"
另一种方法来剥皮这只猫。
我做了一些基准,最快的方法是使用String#<<
方法。 使用StringIO
有点慢。
s = ""; Benchmark.measure{5000000.times{s << "some string"}} => 3.620000 0.100000 3.720000 ( 3.970463) >> s = StringIO.new; Benchmark.measure{5000000.times{s << "some string"}} => 4.730000 0.120000 4.850000 ( 5.329215)
使用String#+
方法连接string是许多次数最慢的方法:
>> s = ""; Benchmark.measure{10000.times{s = s + "some string"}} => 0.700000 0.560000 1.260000 ( 1.420272) >> s = ""; Benchmark.measure{10000.times{s << "some string"}} => 0.000000 0.000000 0.000000 ( 0.005639)
所以我认为正确的答案是相当于Java的StringBuffer
是在Ruby中简单地使用String#<<
。
你的例子在Ruby中工作 – 我只是试了一下。
irb(main):001:0> require 'stringio' => true irb(main):002:0> s = StringIO.new => #<StringIO:0x2ced9a0> irb(main):003:0> s << 'foo' => #<StringIO:0x2ced9a0> irb(main):004:0> s << 'bar' => #<StringIO:0x2ced9a0> irb(main):005:0> s.string => "foobar"
除非我错过了使用to_s的原因 – 只输出对象id。
那么,Ruby中的StringBuffer并不是非常必要,主要是因为Ruby中的string是可变的…因此,您可以通过修改现有string来构buildstring,而不是用每个concat构造新的string。
注意,你也可以使用特殊的string语法,在那里你可以build立一个string来引用string中的其他variables,这使得string的构造非常可读。 考虑:
first = "Mike" last = "Stone" name = "#{first} #{last}"
这些string也可以包含expression式,而不仅仅是variables,例如:
str = "The count will be: #{count + 1}" count = count + 1