Pregunta

Hace poco leí un bonito correo sobre el uso StringIO en Rubí.Lo que el autor no menciona, sin embargo, es que StringIO es solo un "yo" No hay "O." Tú no poder haz esto, por ejemplo:

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

Ruby realmente necesita un StringBuffer como el que tiene Java.Los StringBuffers tienen dos propósitos importantes.Primero, te permiten probar la mitad de salida de lo que hace StringIO de Ruby.En segundo lugar, son útiles para construir cadenas largas a partir de piezas pequeñas, algo que Joel nos recuerda una y otra vez que, por lo demás, es muy, muy lento.

¿Existe un buen reemplazo?

Es cierto que las cadenas en Ruby son mutables, pero eso no significa que siempre debamos confiar en esa funcionalidad.Si stuff es grande, los requisitos de rendimiento y memoria de este, por ejemplo, son realmente malos.

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

La forma "correcta" de hacer esto en Java es:

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

Aunque mi Java está un poco oxidado.

¿Fue útil?

Solución

Miré la documentación de Ruby para StringIO, y parece que lo que quieres es StringIO#string, no StringIO#to_s

Por lo tanto, cambie su código a:

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

Otros consejos

Al igual que otros objetos de tipo IO en Ruby, cuando escribes en un IO, el puntero de carácter avanza.

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

Hice algunos puntos de referencia y el enfoque más rápido es usar el String#<< método.Usando StringIO es un poco más lento.

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)

Concatenar cadenas usando el String#+ El método es el enfoque más lento en muchos órdenes de magnitud:

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)

Entonces creo que la respuesta correcta es que el equivalente a Java StringBuffer es simplemente usar String#<< en Rubí.

Su ejemplo funciona en Ruby; lo acabo de probar.

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"

A menos que me esté perdiendo la razón por la que estás usando to_s, eso solo genera la identificación del objeto.

Bueno, un StringBuffer no es tan necesario en Ruby, principalmente porque las cadenas en Ruby son mutables...por lo tanto, puede crear una cadena modificando la cadena existente en lugar de construir nuevas cadenas con cada concat.

Como nota, también puede usar una sintaxis de cadena especial donde puede crear una cadena que haga referencia a otras variables dentro de la cadena, lo que hace que la construcción de cadenas sea muy legible.Considerar:

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

Estas cadenas también pueden contener expresiones, no solo variables...como:

str = "The count will be: #{count + 1}"
count = count + 1
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top