最近读了一篇不错的 邮政 关于使用 StringIO 在红宝石中。但作者没有提到的是 StringIO 只是一个“我”没有“ O”。你 不能 这样做,例如:

s = StringIO.new
s << 'foo'
s << 'bar'
s.to_s
# => should be "foo\nbar"
# => really is ''`

Ruby 确实需要一个 StringBuffer,就像 Java 一样。StringBuffer 有两个重要用途。首先,它们让您测试 Ruby 的 StringIO 的输出一半。其次,它们对于从小部件构建长字符串很有用——乔尔一遍又一遍地提醒我们,否则的话会非常非常慢。

有好的替代品吗?

Ruby 中的字符串确实是可变的,但这并不意味着我们应该始终依赖该功能。如果 stuff 很大的话,这个对性能和内存的要求确实很糟糕。

result = stuff.map(&:to_s).join(' ')

在 Java 中执行此操作的“正确”方法是:

result = StringBuffer.new("")
for(String s : stuff) {
  result.append(s);
}

虽然我的Java有点生疏了。

有帮助吗?

解决方案

我查看了 ruby​​ 文档 StringIO, ,看起来你想要的是 StringIO#string, , 不是 StringIO#to_s

因此,将您的代码更改为:

s = StringIO.new
s << 'foo'
s << 'bar'
s.string

其他提示

与 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 只是简单地使用 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。

好吧,StringBuffer 在 Ruby 中并不是那么必要,主要是因为 Ruby 中的字符串是可变的......因此,您可以通过修改现有字符串来构建字符串,而不是每次连接都构建新字符串。

请注意,您还可以使用特殊的字符串语法,在其中构建引用字符串中其他变量的字符串,这使得字符串构造非常可读。考虑:

first = "Mike"
last = "Stone"
name = "#{first} #{last}"

这些字符串还可以包含表达式,而不仅仅是变量......例如:

str = "The count will be: #{count + 1}"
count = count + 1
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top