Concatenación de cadenas en Ruby
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 cuál es la diferencia entre <<
y +
?
10 answers
Puedes hacerlo de varias maneras:
- Como mostraste con
<<
pero esa no es la forma habitual -
Con interpolación de cadena
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 (sin embargo, no medido). Los tres métodos lanzarán un error constante no inicializado cuando ROOT_DIR es nil.
Cuando se trata de nombres de ruta, es posible que desee utilizar File.join
para evitar problemas con el separador de nombres de ruta.
Al final, es una cuestión de gusto.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-01 20:14:57
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 mano izquierda, y +
no.
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"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-27 02:52:15
Si solo está concatenando rutas, puede usar el propio archivo de Ruby.método de unión.
source = File.join(ROOT_DIR, project, 'App.config')
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-18 13:22:32
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 anula 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)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-01 13:02:46
Dado que esta es una ruta, probablemente usaría array y join:
source = [ROOT_DIR, project, 'App.config'] * '/'
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-18 13:14:23
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 la RM es pesada.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-13 18:06:02
Preferiría usar Pathname:
require 'pathname' # pathname is in stdlib
Pathname(ROOT_DIR) + project + 'App.config'
Acerca de <<
y +
de ruby docs:
+
: 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 la memoria más pesada) y lo que será si el primer operando es Fixnum (<<
agregará como si fuera un carácter con código igual a ese número, +
elevará error)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-27 02:53:14
Déjame mostrarte toda mi experiencia con eso.
Tuve una consulta que devolvió 32k de registros, para cada registro llamé a un método para formatear ese registro de base de datos en una cadena formateada y luego concatenar en una cadena que al final de todo este proceso se convertirá en un archivo en disco.
Mi problema era que por el registro va, alrededor de 24k, el proceso de concatenar la cadena se volvió un dolor.
Estaba haciendo eso usando el '+'normal operador.
Cuando cambié a '
Entonces, recordé mis viejos tiempos - algo así como 1998 - cuando estaba usando Java y concatenando String usando '+' y cambié de String a StringBuffer (y ahora nosotros, desarrolladores de Java tenemos el StringBuilder).
Creo que el proceso de + /
La primera reasigna todo el objeto en la memoria y la otra solo apunta a una nueva dirección.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-03 20:11:33
¿Concatenación dices? ¿Qué tal #concat
método 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 denomina <<
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-12 03:48:00
Aquí hay más formas de hacer esto:
"String1" + "String2"
"#{String1} #{String2}"
String1<<String2
Y así sucesivamente ...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-25 20:50:49