Frage

Ich habe kürzlich einen schönen Artikel gelesen Post über die Verwendung StringIO in Ruby.Was der Autor jedoch nicht erwähnt, ist das StringIO ist nur ein "I." Es gibt kein "O" Du kippen Mach das zum Beispiel:

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

Ruby braucht wirklich einen StringBuffer, genau wie den, den Java hat.StringBuffers dienen zwei wichtigen Zwecken.Erstens können Sie damit die Ausgabehälfte von Rubys StringIO testen.Zweitens sind sie nützlich, um aus kleinen Teilen lange Saiten aufzubauen – etwas, woran Joel uns immer wieder erinnert, ist ansonsten sehr, sehr langsam.

Gibt es einen guten Ersatz?

Es stimmt, dass Strings in Ruby veränderbar sind, aber das bedeutet nicht, dass wir uns immer auf diese Funktionalität verlassen sollten.Wenn stuff ist groß, der Leistungs- und Speicherbedarf hierfür ist beispielsweise wirklich schlecht.

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

Der „richtige“ Weg, dies in Java zu tun, ist:

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

Allerdings ist mein Java etwas eingerostet.

War es hilfreich?

Lösung

Ich habe mir die Ruby-Dokumentation angesehen StringIO, und es sieht so aus, als ob das ist, was Sie wollen StringIO#string, nicht StringIO#to_s

Ändern Sie daher Ihren Code wie folgt:

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

Andere Tipps

Wie bei anderen Objekten vom Typ IO in Ruby wird der Zeichenzeiger beim Schreiben in ein IO vorgerückt.

>> s = StringIO.new
=> #<StringIO:0x3659d4>
>> s << 'foo'
=> #<StringIO:0x3659d4>
>> s << 'bar'
=> #<StringIO:0x3659d4>
>> s.pos
=> 6
>> s.rewind
=> 0
>> s.read
=> "foobar"

Ich habe einige Benchmarks durchgeführt und der schnellste Ansatz ist die Verwendung von String#<< Methode.Benutzen StringIO ist etwas langsamer.

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)

Verketten von Zeichenfolgen mithilfe von String#+ Methode ist um viele Größenordnungen der langsamste Ansatz:

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)

Daher denke ich, dass die richtige Antwort das Äquivalent zu Java ist StringBuffer ist einfach zu verwenden String#<< in Ruby.

Ihr Beispiel funktioniert in Ruby – ich habe es gerade ausprobiert.

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"

Sofern mir nicht der Grund fehlt, warum Sie to_s verwenden, wird nur die Objekt-ID ausgegeben.

Nun, ein StringBuffer ist in Ruby nicht ganz so notwendig, hauptsächlich weil Strings in Ruby veränderbar sind ...Sie können also eine Zeichenfolge erstellen, indem Sie die vorhandene Zeichenfolge ändern, anstatt bei jeder Konkatierung neue Zeichenfolgen zu erstellen.

Hinweis: Sie können auch eine spezielle String-Syntax verwenden, mit der Sie einen String erstellen können, der auf andere Variablen innerhalb des Strings verweist, was zu einer sehr gut lesbaren String-Konstruktion führt.Halten:

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

Diese Zeichenfolgen können auch Ausdrücke enthalten, nicht nur Variablen ...wie zum Beispiel:

str = "The count will be: #{count + 1}"
count = count + 1
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top