为什么Ruby没有真正的StringBuffer或者StringIO?

时间:2020-03-05 18:39:29  来源:igfitidea点击:

我最近读了一篇关于在Ruby中使用StringIO的不错的文章。不过,作者没有提及的是StringIO只是一个" I"。没有" O"。我们不能这样做,例如:

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

就像Java一样,Ruby确实需要一个StringBuffer。 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中的字符串是可变的...因此,我们可以通过修改现有字符串来构建字符串,而不是使用每个concat构造新的字符串。

需要注意的是,我们还可以使用特殊的字符串语法,在其中我们可以构建一个引用该字符串中其他变量的字符串,从而使字符串的构造非常容易理解。考虑:

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

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

str = "The count will be: #{count + 1}"
count = count + 1

回答

我查看了StringIO的ruby文档,看起来我们想要的是StringIO#string,而不是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"

除非我错过我们使用仅输出对象ID的to_s的原因,否则。

回答

与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"

换皮这只猫的另一种方法。