Ruby에서 문자열을 연결하는보다 우아한 방법을 찾고 있습니다.
다음 줄이 있습니다.
source = "#{ROOT_DIR}/" << project << "/App.config"
더 좋은 방법이 있습니까?
그리고 그 문제의 차이 무엇 <<
과 +
?
답변
여러 가지 방법으로이를 수행 할 수 있습니다.
- 당신이 보여 주
<<
었지만 그것은 일반적인 방법 이 아닙니다 -
문자열 보간
source = "#{ROOT_DIR}/#{project}/App.config"
-
와
+
source = "#{ROOT_DIR}/" + project + "/App.config"
두 번째 방법은 내가 본 것보다 메모리 / 속도면에서 더 효율적인 것으로 보입니다 (측정하지는 않음). ROOT_DIR이 nil이면 세 가지 방법 모두 초기화되지 않은 상수 오류를 발생시킵니다.
경로 이름을 다룰 때 File.join
경로 이름 구분 기호가 엉망이되는 것을 피하기 위해 사용할 수 있습니다 .
결국, 그것은 맛의 문제입니다.
답변
그만큼 +
운영자는 일반적인 연결 선택이며, 아마도 CONCATENATE 문자열 가장 빠른 방법입니다.
차이 +
와 <<
즉 <<
그 왼쪽에있는 물체를 변경 한 +
하지 않는다.
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"
답변
경로를 연결하는 경우 Ruby 고유의 File.join 메소드를 사용할 수 있습니다.
source = File.join(ROOT_DIR, project, 'App.config')
답변
에서 http://greyblake.com/blog/2012/09/02/ruby-perfomance-tricks/
후자는 임시 객체를 만들고 첫 번째 객체를 새 객체로 재정의하므로 <<
aka를 사용하는 concat
것이보다 효율적 +=
입니다.
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
산출:
____________________________________________________________
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)
답변
이것이 경로이기 때문에 아마도 배열을 사용하고 결합 할 것입니다.
source = [ROOT_DIR, project, 'App.config'] * '/'
답변
이 요점에서 영감을 얻은 또 다른 벤치 마크가 있습니다. 동적 및 사전 정의 된 문자열에 대한 연결 ( +
), 추가 ( <<
) 및 보간 ( #{}
)을 비교합니다 .
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
산출:
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)
결론 : MRI의 보간법은 무겁습니다.
답변
Pathname을 사용하고 싶습니다.
require 'pathname' # pathname is in stdlib
Pathname(ROOT_DIR) + project + 'App.config'
약 <<
및 +
루비 문서에서 :
+
: str에 연결된 other_str을 포함 하는 새로운 문자열을 반환
<<
: 주어진 객체를 str에 연결합니다. 오브젝트가 0-255 사이의 Fixnum 인 경우, 연결하기 전에 문자로 변환됩니다.
차이는 첫 번째 피연산자로 될 것입니다 때문에 ( <<
장소 변경합니다 +
(첫 번째 피연산자가 Fixnum이라는 경우가 될 것입니다 무엇을 반환 새 문자열이 메모리가 무거운 정도) <<
가 코드 문자가 그 수만큼 인 것처럼 추가합니다, +
올릴 것이다 오류)