str - manejo de cadenas en ruby
Concatenación de cuerdas en Ruby (11)
Estoy buscando una forma más elegante de concatenar cadenas en Ruby.
Tengo la siguiente línea:
source = "#{ROOT_DIR}/" << project << "/App.config"
¿Hay una manera más agradable de hacer esto?
Y para eso, ¿cuál es la diferencia entre <<
y +
?
Aquí hay más formas de hacer esto:
"String1" + "String2"
"#{String1} #{String2}"
String1<<String2
Y así ...
Aquí hay otro punto de referencia inspirado por esta esencia . Compara la concatenación ( +
), la adición ( <<
) y la interpolación ( #{}
) para cadenas dinámicas y predefinidas.
require ''benchmark''
# we will need the CAPTION and FORMAT constants:
include Benchmark
count = 100_000
puts "Dynamic strings"
Benchmark.benchmark(CAPTION, 7, FORMAT) do |bm|
bm.report("concat") { count.times { 11.to_s + ''/'' + 12.to_s } }
bm.report("append") { count.times { 11.to_s << ''/'' << 12.to_s } }
bm.report("interp") { count.times { "#{11}/#{12}" } }
end
puts "/nPredefined strings"
s11 = "11"
s12 = "12"
Benchmark.benchmark(CAPTION, 7, FORMAT) do |bm|
bm.report("concat") { count.times { s11 + ''/'' + s12 } }
bm.report("append") { count.times { s11 << ''/'' << s12 } }
bm.report("interp") { count.times { "#{s11}/#{s12}" } }
end
salida:
Dynamic strings
user system total real
concat 0.050000 0.000000 0.050000 ( 0.047770)
append 0.040000 0.000000 0.040000 ( 0.042724)
interp 0.050000 0.000000 0.050000 ( 0.051736)
Predefined strings
user system total real
concat 0.030000 0.000000 0.030000 ( 0.024888)
append 0.020000 0.000000 0.020000 ( 0.023373)
interp 3.160000 0.160000 3.320000 ( 3.311253)
Conclusión: la interpolación en RMN es pesada.
Déjame mostrarte toda mi experiencia con eso.
Tuve una consulta que devolvió 32k de registros, por cada registro que llamé a un método para formatear ese registro de base de datos en una cadena con formato y luego concatenarla en una Cadena que al final de todo este proceso se convertirá en un archivo en el disco.
Mi problema fue que según el registro, alrededor de 24k, el proceso de concatenar el String se convirtió en un dolor.
Estaba haciendo eso usando el operador regular ''+''.
Cuando cambié a ''<<'' fue como magia. Fue realmente rápido.
Entonces, recordé mis viejos tiempos, más o menos 1998, cuando estaba usando Java y concatenando String usando ''+'' y cambié de String a StringBuffer (y ahora nosotros, el desarrollador de Java tenemos StringBuilder).
Creo que el proceso de + / << en el mundo de Ruby es el mismo que el de + / StringBuilder.append en el mundo de Java.
La primera reasigna todo el objeto en la memoria y la otra simplemente apunta a una nueva dirección.
El operador +
es la opción de concatenación normal, y es probablemente la forma más rápida de concatenar cadenas.
La diferencia entre +
y <<
es que <<
cambia el objeto en su lado izquierdo, y +
no lo hace.
irb(main):001:0> s = ''a''
=> "a"
irb(main):002:0> s + ''b''
=> "ab"
irb(main):003:0> s
=> "a"
irb(main):004:0> s << ''b''
=> "ab"
irb(main):005:0> s
=> "ab"
La concatenación que dices? ¿Qué #concat
método #concat
entonces?
a = ''foo''
a.object_id #=> some number
a.concat ''bar'' #=> foobar
a.object_id #=> same as before -- string a remains the same object
Para ser justos, concat
se presenta como <<
.
Preferiría usar Pathname:
require ''pathname'' # pathname is in stdlib
Pathname(ROOT_DIR) + project + ''App.config''
sobre <<
y +
de documentos de ruby:
+
: Devuelve una nueva cadena que contiene other_str concatenada a str
<<
: Concatena el objeto dado a str. Si el objeto es un Fixnum entre 0 y 255, se convierte en un carácter antes de la concatenación.
así que la diferencia está en lo que se convierte en el primer operando ( <<
hace cambios en su lugar, +
devuelve una nueva cadena, por lo que es más pesada la memoria) y qué ocurrirá si el primer operando es Fixnum ( <<
se agregará como si fuera un carácter con código igual ese número, +
generará error)
Puede usar el operador +
o <<
, pero en ruby .concat
función es la más preferible, ya que es mucho más rápida que otros operadores. Puedes usarlo como.
source = "#{ROOT_DIR}/".concat(project.concat.("/App.config"))
Puedes hacerlo de varias maneras:
- Como se muestra con
<<
pero esa no es la forma habitual. Con interpolación de cuerdas.
source = "#{ROOT_DIR}/#{project}/App.config"
con
+
source = "#{ROOT_DIR}/" + project + "/App.config"
El segundo método parece ser más eficiente en términos de memoria / velocidad de lo que he visto (aunque no se ha medido). Los tres métodos arrojarán un error constante sin inicializar cuando ROOT_DIR es nulo.
Cuando se trata de File.join
acceso, es posible que desee utilizar File.join
para evitar problemas con el separador de ruta de acceso.
Al final, es cuestión de gustos.
Si solo está concatenando rutas, puede usar el método File.join de Ruby.
source = File.join(ROOT_DIR, project, ''App.config'')
Ya que esta es una ruta probablemente usaría array y uniría:
source = [ROOT_DIR, project, ''App.config''] * ''/''
de http://greyblake.com/blog/2012/09/02/ruby-perfomance-tricks/
Usar <<
aka concat
es mucho más eficiente que +=
, ya que este último crea un objeto temporal y reemplaza el primer objeto con el nuevo objeto.
require ''benchmark''
N = 1000
BASIC_LENGTH = 10
5.times do |factor|
length = BASIC_LENGTH * (10 ** factor)
puts "_" * 60 + "/nLENGTH: #{length}"
Benchmark.bm(10, ''+= VS <<'') do |x|
concat_report = x.report("+=") do
str1 = ""
str2 = "s" * length
N.times { str1 += str2 }
end
modify_report = x.report("<<") do
str1 = "s"
str2 = "s" * length
N.times { str1 << str2 }
end
[concat_report / modify_report]
end
end
salida:
____________________________________________________________
LENGTH: 10
user system total real
+= 0.000000 0.000000 0.000000 ( 0.004671)
<< 0.000000 0.000000 0.000000 ( 0.000176)
+= VS << NaN NaN NaN ( 26.508796)
____________________________________________________________
LENGTH: 100
user system total real
+= 0.020000 0.000000 0.020000 ( 0.022995)
<< 0.000000 0.000000 0.000000 ( 0.000226)
+= VS << Inf NaN NaN (101.845829)
____________________________________________________________
LENGTH: 1000
user system total real
+= 0.270000 0.120000 0.390000 ( 0.390888)
<< 0.000000 0.000000 0.000000 ( 0.001730)
+= VS << Inf Inf NaN (225.920077)
____________________________________________________________
LENGTH: 10000
user system total real
+= 3.660000 1.570000 5.230000 ( 5.233861)
<< 0.000000 0.010000 0.010000 ( 0.015099)
+= VS << Inf 157.000000 NaN (346.629692)
____________________________________________________________
LENGTH: 100000
user system total real
+= 31.270000 16.990000 48.260000 ( 48.328511)
<< 0.050000 0.050000 0.100000 ( 0.105993)
+= VS << 625.400000 339.800000 NaN (455.961373)