56

最近、Rubyでの使用に関するすばらしい記事を読みました。StringIOただし、著者が言及していないのは、それStringIOが単なる「私」であるということです。「お」がない。たとえば、次のようにすることはできません。

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

Ruby は、Java が持っているのと同じように StringBuffer を実際に必要とします。StringBuffers には 2 つの重要な目的があります。まず、Ruby の StringIO が行うことの半分の出力をテストできます。第二に、それらは小さな部品から長い文字列を構築するのに役立ちます. Joel が何度も私たちに思い出させてくれることは、そうでなければ非常に遅いことです.

良い代替品はありますか?

Ruby の文字列が変更可能であることは事実ですが、それは常にその機能に依存する必要があるという意味ではありません。が大きい場合stuff、たとえば、これのパフォーマンスとメモリの要件は非常に悪いです。

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

Javaでこれを行う「正しい」方法は次のとおりです。

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

私のJavaは少し錆びていますが。

4

5 に答える 5

121

の ruby​​ ドキュメントを見たところ、StringIOあなたが望むのはStringIO#stringではなくStringIO#to_s

したがって、コードを次のように変更します。

s = StringIO.new
s << 'foo'
s << 'bar'
s.string
于 2008-08-13T20:41:29.153 に答える
34

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"
于 2009-08-09T19:39:21.843 に答える
24

私はいくつかのベンチマークを行いましたが、最速のアプローチはこの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 で使用されているということだと思います。

于 2012-11-07T18:57:33.277 に答える
12

あなたの例は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 を出力するだけです。

于 2008-08-13T20:46:30.500 に答える
3

主にRubyの文字列は変更可能であるため、RubyではStringBufferはそれほど必要ではありません...したがって、各連結で新しい文字列を構築する代わりに、既存の文字列を変更して文字列を構築できます。

注意として、文字列内の他の変数を参照する文字列を構築できる特別な文字列構文を使用することもできます。これにより、非常に読みやすい文字列構築が可能になります。検討:

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

これらの文字列には、変数だけでなく、次のような式を含めることもできます。

str = "The count will be: #{count + 1}"
count = count + 1
于 2008-08-13T20:31:29.050 に答える