Domanda

Recentemente ho letto un bel inviare sull'utilizzo StringIO in Rubino.Ciò che l'autore non menziona, però, è questo StringIO è solo un "I." Non c'è "O." Voi non posso fai questo, ad esempio:

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

Ruby ha davvero bisogno di uno StringBuffer proprio come quello di Java.Gli StringBuffer hanno due scopi importanti.Innanzitutto, ti consentono di testare l'output metà di ciò che fa StringIO di Ruby.In secondo luogo, sono utili per costruire lunghe stringhe da piccole parti - qualcosa che Joel ci ricorda più e più volte è altrimenti molto, molto lento.

Esiste un buon sostituto?

È vero che le stringhe in Ruby sono mutabili, ma ciò non significa che dovremmo sempre fare affidamento su quella funzionalità.Se stuff è grande, le prestazioni e i requisiti di memoria di questo, ad esempio, sono davvero pessimi.

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

Il modo "corretto" per farlo in Java è:

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

Anche se il mio Java è un po' arrugginito.

È stato utile?

Soluzione

Ho guardato la documentazione di Ruby per StringIO, e sembra che ciò che desideri sia StringIO#string, non StringIO#to_s

Quindi, cambia il tuo codice in:

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

Altri suggerimenti

Come altri oggetti di tipo IO in Ruby, quando scrivi su un IO, il puntatore del carattere avanza.

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

Ho eseguito alcuni benchmark e l'approccio più rapido è utilizzare il file String#<< metodo.Utilizzando StringIO è un po' più 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)

Concatenazione di stringhe utilizzando il metodo String#+ Il metodo è l'approccio più lento per molti ordini di grandezza:

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)

Quindi penso che la risposta giusta sia l'equivalente di Java StringBuffer sta semplicemente usando String#<< in Rubino.

Il tuo esempio funziona in Ruby: l'ho appena provato.

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 meno che non mi manchi il motivo per cui stai usando to_s: restituisce solo l'ID dell'oggetto.

Bene, uno StringBuffer non è così necessario in Ruby, principalmente perché le stringhe in Ruby sono mutabili...quindi puoi creare una stringa modificando la stringa esistente invece di costruire nuove stringhe con ogni concat.

Come nota, puoi anche utilizzare una sintassi speciale delle stringhe in cui puoi creare una stringa che fa riferimento ad altre variabili all'interno della stringa, il che rende la costruzione della stringa molto leggibile.Prendere in considerazione:

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

Queste stringhe possono contenere anche espressioni, non solo variabili...ad esempio:

str = "The count will be: #{count + 1}"
count = count + 1
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top