Konkatenacja łańcuchów w Ruby

Szukam bardziej eleganckiego sposobu łączenia sznurków w Ruby.

Mam następujący wiersz:

source = "#{ROOT_DIR}/" << project << "/App.config"
Czy jest na to lepszy sposób?

I jaka jest różnica między << A +?

Author: idmean, 2008-12-18

10 answers

Możesz to zrobić na kilka sposobów:]}

  1. Jak pokazałeś z << ale to nie jest zwykły sposób
  2. Z interpolacją ciągu

    source = "#{ROOT_DIR}/#{project}/App.config"
    
  3. Z +

    source = "#{ROOT_DIR}/" + project + "/App.config"
    

Druga metoda wydaje się być bardziej efektywna pod względem pamięci/szybkości z tego, co widziałem (ale nie mierzona). Wszystkie trzy metody wywołają niezainicjowany stały błąd, gdy ROOT_DIR jest zerowy.

Gdy masz do czynienia z nazwami ścieżek, możesz użyć File.join aby uniknąć bałaganu z separatorem pathname.

Koniec końców, to kwestia gustu.
 492
Author: Keltia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-01 20:14:57

Operator + jest normalnym wyborem konkatenacji i jest prawdopodobnie najszybszym sposobem łączenia łańcuchów.

Różnica między + i << jest taka, że << zmienia obiekt po lewej stronie, a + NIE.

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"
 83
Author: Matt Burke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-27 02:52:15

Jeśli tylko łączysz ścieżki, możesz użyć własnego pliku Rubiego.metoda join.

source = File.join(ROOT_DIR, project, 'App.config')
 74
Author: georg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-18 13:22:32

Z http://greyblake.com/blog/2012/09/02/ruby-perfomance-tricks/

Użycie << aka concat jest znacznie wydajniejsze niż +=, ponieważ ten ostatni tworzy obiekt czasowy i nadpisuje pierwszy obiekt nowym.

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

Wyjście:

____________________________________________________________
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)
 19
Author: Danny,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-01 13:02:46

Ponieważ jest to ścieżka prawdopodobnie użyłbym array I join:

source = [ROOT_DIR, project, 'App.config'] * '/'
 9
Author: Dejan Simic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-18 13:14:23

Oto kolejny benchmark zainspirowany tym gist . Porównuje concatenation (+), appending (<<) i interpolation (#{}) dla dynamicznych i predefiniowanych łańcuchów.

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

Wyjście:

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)

Wniosek: interpolacja w MRI jest ciężka.

 7
Author: Adobe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-13 18:06:02

Wolałbym użyć Pathname:

require 'pathname' # pathname is in stdlib
Pathname(ROOT_DIR) + project + 'App.config'

O << i + z Ruby docs:

+: zwraca new łańcuch zawierający other_str skonkatenowany do str

<<: Konkatenuje dany obiekt do str. Jeśli obiekt jest Fixnum z zakresu od 0 do 255, jest konwertowany na znak przed konkatenacją.

Więc różnica polega na tym, co staje się pierwszym operandem (<< wprowadza zmiany w miejscu, + zwraca nowy ciąg, więc jest to pamięć cięższa) i co będzie jeśli pierwszym operandem jest Fixnum (<< doda tak, jakby był to znak o kodzie równym tej liczbie, + wywoła błąd)

 6
Author: tig,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-27 02:53:14

Pozwól, że pokażę Ci całe moje doświadczenie z tym.

Miałem zapytanie, które zwróciło 32K rekordów, dla każdego rekordu wywołałem metodę sformatowania tego rekordu bazy danych do sformatowanego łańcucha i następnie połączyłem go w łańcuch, który pod koniec całego tego procesu zamieni się w plik na dysku.

Moim problemem było to, że przy zapisie idzie, około 24k, proces łączenia struny zwrócił się ból.

Robiłem to używając zwykłego"+" centrala.

Kiedy zmieniłem na '

Tak więc, przypomniałem sobie moje stare czasy-tak jakby 1998 - kiedy używałem Javy i łączyłem String za pomocą ' + ' i zmieniałem z String Na StringBuffer (a teraz my, Java developer mamy StringBuilder).

Uważam, że proces + /

Pierwszy zapisuje cały obiekt w pamięci, a drugi tylko wskazuje pod nowy adres.

 6
Author: Marcio Mangar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-03 20:11:33

Mówisz o konkatenacji? A może metoda #concat?

a = 'foo'
a.object_id #=> some number
a.concat 'bar' #=> foobar
a.object_id #=> same as before -- string a remains the same object

W całej sprawiedliwości, {[2] } jest aliased jako <<.

 5
Author: Boris Stitnicky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-12 03:48:00

Oto więcej sposobów, aby to zrobić:

"String1" + "String2"

"#{String1} #{String2}"

String1<<String2

I tak dalej ...

 5
Author: Imran Alavi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-25 20:50:49