Pergunta

Recentemente li um bom publicar em usar StringIO em Rubi.O que o autor não menciona, porém, é que StringIO é apenas um "eu". Não há "O." Você não pode faça isso, por exemplo:

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

Ruby realmente precisa de um StringBuffer igual ao que Java possui.StringBuffers servem a dois propósitos importantes.Primeiro, eles permitem testar a saída com metade do que o StringIO do Ruby faz.Em segundo lugar, eles são úteis para construir cordas longas a partir de peças pequenas - algo que Joel nos lembra repetidamente é muito lento.

Existe um bom substituto?

É verdade que Strings em Ruby são mutáveis, mas isso não significa que devemos sempre confiar nessa funcionalidade.Se stuff é grande, os requisitos de desempenho e memória deste, por exemplo, são muito ruins.

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

A maneira "correta" de fazer isso em Java é:

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

Embora meu Java esteja um pouco enferrujado.

Foi útil?

Solução

Eu olhei a documentação do Ruby para StringIO, e parece que o que você quer é StringIO#string, não StringIO#to_s

Assim, altere seu código para:

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

Outras dicas

Como outros objetos do tipo IO em Ruby, quando você escreve em um IO, o ponteiro do caractere avança.

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

Fiz alguns benchmarks e a abordagem mais rápida é usar o String#<< método.Usando StringIO é um pouco mais 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)

Concatenando strings usando o String#+ O método é a abordagem mais lenta em muitas ordens de magnitude:

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)

Então acho que a resposta certa é que o equivalente ao Java StringBuffer está simplesmente usando String#<< em Rubi.

Seu exemplo funciona em Ruby - acabei de tentar.

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 eu esteja perdendo o motivo pelo qual você está usando to_s - isso apenas gera o ID do objeto.

Bem, um StringBuffer não é tão necessário em Ruby, principalmente porque Strings em Ruby são mutáveis...assim você pode construir uma string modificando a string existente em vez de construir novas strings com cada concat.

Como observação, você também pode usar uma sintaxe de string especial onde você pode construir uma string que faça referência a outras variáveis ​​dentro da string, o que torna a construção de string muito legível.Considerar:

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

Essas strings também podem conter expressões, não apenas variáveis...como:

str = "The count will be: #{count + 1}"
count = count + 1
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top