提问人:James A. Rosen 提问时间:8/14/2008 最后编辑:Ajedi32James A. Rosen 更新时间:4/20/2019 访问量:31369
为什么 Ruby 没有真正的 StringBuffer 或 StringIO?
Why doesn't Ruby have a real StringBuffer or StringIO?
问:
我最近读了一篇关于在 Ruby 中使用 Ruby 的好文章。然而,作者没有提到的是,这只是一个“我”。没有“O”。您不能这样做,例如:StringIO
StringIO
s = StringIO.new
s << 'foo'
s << 'bar'
s.to_s
# => should be "foo\nbar"
# => really is ''`
Ruby 确实需要一个 StringBuffer,就像 Java 一样。StringBuffers 有两个重要用途。首先,它们让你测试 Ruby 的 StringIO 的输出一半。其次,它们对于从小零件建立长弦很有用——乔尔一遍又一遍地提醒我们,否则会非常非常缓慢。
有好的替代品吗?
Ruby 中的字符串确实是可变的,但这并不意味着我们应该始终依赖该功能。例如,如果很大,则对性能和内存的要求非常糟糕。stuff
result = stuff.map(&:to_s).join(' ')
在 Java 中执行此操作的“正确”方法是:
result = StringBuffer.new("")
for(String s : stuff) {
result.append(s);
}
虽然我的Java有点生疏。
答:
好吧,StringBuffer 在 Ruby 中并不是那么必要,主要是因为 Ruby 中的字符串是可变的......因此,您可以通过修改现有字符串来构建字符串,而不是使用每个连接构造新字符串。
需要注意的是,您还可以使用特殊的字符串语法,您可以在其中构建一个字符串,该字符串引用字符串中的其他变量,这使得字符串构造具有非常强的可读性。考虑:
first = "Mike"
last = "Stone"
name = "#{first} #{last}"
这些字符串还可以包含表达式,而不仅仅是变量......如:
str = "The count will be: #{count + 1}"
count = count + 1
评论
我查看了 的 ruby 文档,看起来您想要的是 StringIO#string
,而不是StringIO
StringIO#to_s
因此,请将代码更改为:
s = StringIO.new
s << 'foo'
s << 'bar'
s.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 中的其他 IO 类型对象一样,当您写入 IO 时,字符指针会前进。
>> s = StringIO.new
=> #<StringIO:0x3659d4>
>> s << 'foo'
=> #<StringIO:0x3659d4>
>> s << 'bar'
=> #<StringIO:0x3659d4>
>> s.pos
=> 6
>> s.rewind
=> 0
>> s.read
=> "foobar"
评论
StringIO#read
StringIO#string
我做了一些基准测试,最快的方法是使用该方法。使用速度有点慢。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 等价的只是在 Ruby 中使用。StringBuffer
String#<<
评论
StringIO
StringIO
上一个:通过命令行向程序发送消息
评论
stuff.inject('') { |res, s| res << s.to_s }