为什么Ruby没有真正的StringBuffer或StringIO?
我最近读了一个很好的post在Ruby中使用StringIO
。然而作者没有提到的是StringIO
只是一个“I”。没有“O”。您无法做到这一点,例如:为什么Ruby没有真正的StringBuffer或StringIO?
s = StringIO.new
s << 'foo'
s << 'bar'
s.to_s
# => should be "foo\nbar"
# => really is ''`
红宝石确实需要一个StringBuffer就像一个Java有。 StringBuffers有两个重要的用途。首先,他们让你测试Ruby的StringIO的输出结果的一半。其次,它们对于从小部件制造长弦很有用 - Joel一再提醒我们的事情是非常缓慢的。
有没有很好的替代品?
这是真的,字符串在Ruby中是可变的,但是,这并不意味着我们应该永远依靠该功能。例如,如果stuff
很大,那么对此的性能和内存要求就非常糟糕。
result = stuff.map(&:to_s).join(' ')
“正确” 的方式在Java中做到这一点是:
result = StringBuffer.new("")
for(String s : stuff) {
result.append(s);
}
虽然我的Java是一个有点生疏。
我看着红宝石文档StringIO
,它看起来像你想要的是StringIO#string
,不StringIO#to_s
因此,你的代码更改为:
s = StringIO.new
s << 'foo'
s << 'bar'
s.string
嘛,一个StringBuffer是不是很在Ruby中必要的,这主要是因为字符串在Ruby中是可变的,所以......你可以通过修改现有的字符串,而不是每个CONCAT构建新的字符串建立一个字符串。
作为一个说明,你还可以使用特殊字符串语法,你可以建立它引用的字符串,这使得非常可读的字符串建筑内的其他变量的字符串。试想一下:
first = "Mike"
last = "Stone"
name = "#{first} #{last}"
这些字符串也可以包含表达式,而不只是变量...如:
str = "The count will be: #{count + 1}"
count = count + 1
你的例子在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中的其他IO类型对象一样,当您写入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#+
方法连接字符串是由好几个数量级最慢的方法:
>> 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#<<
。
“Mega Maid?”从来没有听说过她。从来没有真正相信StringBuffers,但我总是用它们来担心有人看到我的代码。但是,真的,这些东西总合起来了吗? – 2009-05-06 01:53:03
可能是'SpaceBalls'的参考。 – 2010-08-30 16:59:35
巨型女佣已被删除作为摆脱*的附带损害。 – 2011-05-09 03:52:29