2012-04-09 35 views
65

Tôi chỉ mới bắt đầu học Ruby (lập trình lần đầu), và có một câu hỏi cơ bản về cú pháp và các cách viết mã khác nhau.Ghép chuỗi so với nội suy trong Ruby

Chris Pine "Learn to Chương trình" dạy cho tôi để viết một chương trình cơ bản như thế này ...

num_cars_again= 2 
puts 'I own ' + num_cars_again.to_s + ' cars.' 

này là tốt, nhưng sau đó tôi loạng choạng trên hướng dẫn về ruby.learncodethehardway.com, và là dạy để viết chương trình chính xác giống như thế này ...

num_cars= 2 
puts "I own #{num_cars} cars." 

cả hai đều ra điều tương tự, nhưng rõ ràng là phương án 2 là một cách ngắn hơn nhiều để làm điều đó.

Có lý do cụ thể nào khiến tôi nên sử dụng một định dạng khác không?

+4

Ugh. Tôi ghét làm thế nào thường xuyên cuốn sách mới bắt đầu dạy cho bạn một cách tự nhiên làm việc mà không ít nhất nói với bạn rằng lựa chọn thay thế tồn tại. 1 cho một câu hỏi hợp pháp chưa được bình chọn. –

+0

Có nhiều tùy chọn hơn được thảo luận tại http://stackoverflow.com/questions/377768/string-concatenation-and-ruby – sameers

Trả lời

62

Bất cứ khi nào TIMTOWTDI (có nhiều cách để thực hiện), bạn nên tìm kiếm ưu và khuyết điểm. Sử dụng "chuỗi suy" (thứ hai) thay vì "nối dây" (người đầu tiên):

Ưu điểm:

  • Ít gõ
  • Tự động gọi to_s cho bạn
  • Nhiều thành ngữ trong cộng đồng Ruby
  • Nhanh hơn để hoàn thành trong thời gian chạy

Nhược điểm:

  • Tự động gọi to_s cho bạn (có thể bạn nghĩ rằng bạn đã có một chuỗi, và to_s đại diện không phải là những gì bạn muốn, và giấu thực tế là nó không phải là một chuỗi)
  • Yêu cầu bạn sử dụng " để phân định chuỗi của bạn thay vì ' (có lẽ bạn có thói quen sử dụng ', hoặc trước đây bạn đã gõ một chuỗi sử dụng đó và chỉ sau đó cần thiết để sử dụng chuỗi suy)
+20

Đừng quên khía cạnh "nó nhanh hơn". Chuỗi nối, trong ví dụ này, phải tạo ra 3 chuỗi trong tổng số, trong khi chuỗi nội suy chỉ tạo ra một chuỗi. –

+4

nếu bạn quan tâm đến điểm chuẩn, nó cũng nhanh hơn: [thử tôi trong REPL] (https://gist.github.com/1704455) – mrlee

+2

Cảm ơn rất nhiều câu trả lời. Câu hỏi nhanh. Tại sao cuốn sách của Chris Pine lại dạy cho con đường dài hơn để làm điều đó? Có lẽ nó là tốt hơn cho một người mới bắt đầu học cách làm nó theo cách lâu hơn? Cuốn sách của anh ấy nói phần lớn thời gian hơn là tốt hơn, vì vậy tôi tự hỏi liệu có lẽ vì một lý do nào đó (vì tôi chỉ đang học), tôi nên tiếp tục làm theo cách của anh ấy hoặc tiến lên phía trước với cách này tốt hơn. Bất kỳ ý tưởng? –

3

@ user1181898 - IMHO, đó là bởi vì nó dễ dàng hơn để xem những gì đang xảy ra. Để @ Phrogz của điểm, chuỗi nội suy tự động gọi to_s cho bạn. Là một người mới bắt đầu, bạn cần phải xem những gì đang xảy ra "dưới mui xe" để bạn tìm hiểu các khái niệm như trái ngược với chỉ học tập bằng rote.

Hãy nghĩ về nó như học toán học. Bạn tìm hiểu cách "dài" để hiểu các khái niệm để bạn có thể thực hiện các lối tắt khi bạn thực sự biết mình đang làm gì. Tôi nói từ kinh nghiệm b/c Tôi không phải là tiên tiến trong Ruby được nêu ra, nhưng tôi đã thực hiện đủ sai lầm để tư vấn cho mọi người về những gì không làm. Hi vọng điêu nay co ich.

+0

Cảm ơn rất nhiều, nó! –

7

Cả nội suy lẫn tính tương hợp đều có điểm mạnh và điểm yếu riêng. Dưới đây tôi đã đưa ra một điểm chuẩn mà rõ ràng chứng minh nơi để sử dụng concatination và nơi để sử dụng nội suy.

require 'benchmark' 

iterations = 1_00_000 
firstname = 'soundarapandian' 
middlename = 'rathinasamy' 
lastname = 'arumugam' 

puts 'With dynamic new strings' 
puts '====================================================' 
5.times do 
    Benchmark.bm(10) do |benchmark| 
    benchmark.report('concatination') do 
     iterations.times do 
     'Mr. ' + firstname + middlename + lastname + ' aka soundar' 
     end 
    end 

    benchmark.report('interpolaton') do 
     iterations.times do 
     "Mr. #{firstname} #{middlename} #{lastname} aka soundar" 
     end 
    end 
    end 
    puts '--------------------------------------------------' 
end 

puts 'With predefined strings' 
puts '====================================================' 
5.times do 
    Benchmark.bm(10) do |benchmark| 
    benchmark.report('concatination') do 
     iterations.times do 
     firstname + middlename + lastname 
     end 
    end 

    benchmark.report('interpolaton') do 
     iterations.times do 
     "#{firstname} #{middlename} #{lastname}" 
     end 
    end 
    end 
    puts '--------------------------------------------------' 
end 

Và dưới đây là kết quả Benchmark

Without predefined strings 
==================================================== 
       user  system  total  real 
concatination 0.170000 0.000000 0.170000 ( 0.165821) 
interpolaton 0.130000 0.010000 0.140000 ( 0.133665) 
-------------------------------------------------- 
       user  system  total  real 
concatination 0.180000 0.000000 0.180000 ( 0.180410) 
interpolaton 0.120000 0.000000 0.120000 ( 0.125051) 
-------------------------------------------------- 
       user  system  total  real 
concatination 0.140000 0.000000 0.140000 ( 0.134256) 
interpolaton 0.110000 0.000000 0.110000 ( 0.111427) 
-------------------------------------------------- 
       user  system  total  real 
concatination 0.130000 0.000000 0.130000 ( 0.132047) 
interpolaton 0.120000 0.000000 0.120000 ( 0.120443) 
-------------------------------------------------- 
       user  system  total  real 
concatination 0.170000 0.000000 0.170000 ( 0.170394) 
interpolaton 0.150000 0.000000 0.150000 ( 0.149601) 
-------------------------------------------------- 
With predefined strings 
==================================================== 
       user  system  total  real 
concatination 0.070000 0.000000 0.070000 ( 0.067735) 
interpolaton 0.100000 0.000000 0.100000 ( 0.099335) 
-------------------------------------------------- 
       user  system  total  real 
concatination 0.060000 0.000000 0.060000 ( 0.061955) 
interpolaton 0.130000 0.000000 0.130000 ( 0.127011) 
-------------------------------------------------- 
       user  system  total  real 
concatination 0.090000 0.000000 0.090000 ( 0.092136) 
interpolaton 0.110000 0.000000 0.110000 ( 0.110224) 
-------------------------------------------------- 
       user  system  total  real 
concatination 0.080000 0.000000 0.080000 ( 0.077587) 
interpolaton 0.110000 0.000000 0.110000 ( 0.112975) 
-------------------------------------------------- 
       user  system  total  real 
concatination 0.090000 0.000000 0.090000 ( 0.088154) 
interpolaton 0.140000 0.000000 0.140000 ( 0.135349) 
-------------------------------------------------- 

Kết luận

Nếu chuỗi đã được xác định và chắc chắn họ sẽ không bao giờ có con số không sử dụng bởi ghép khác sử dụng interpolation.Use một thích hợp mà sẽ cho kết quả hiệu suất tốt hơn so với hiệu suất dễ thụt lề.

+0

phiên bản Ruby nào bạn đã sử dụng? –

1

Nếu bạn đang sử dụng chuỗi làm bộ đệm, tôi nhận thấy rằng việc sử dụng tính năng nối (String#concat) sẽ nhanh hơn.

require 'benchmark/ips' 

puts "Ruby #{RUBY_VERSION} at #{Time.now}" 
puts 

firstname = 'soundarapandian' 
middlename = 'rathinasamy' 
lastname = 'arumugam' 

Benchmark.ips do |x| 
    x.report("String\#<<") do |i| 
     buffer = String.new 

     while (i -= 1) > 0 
      buffer << 'Mr. ' << firstname << middlename << lastname << ' aka soundar' 
     end 
    end 

    x.report("String interpolate") do |i| 
     buffer = String.new 

     while (i -= 1) > 0 
      buffer << "Mr. #{firstname} #{middlename} #{lastname} aka soundar" 
     end 
    end 

    x.compare! 
end 

Kết quả:

Ruby 2.3.1 at 2016-11-15 15:03:57 +1300 

Warming up -------------------------------------- 
      String#<< 230.615k i/100ms 
    String interpolate 234.274k i/100ms 
Calculating ------------------------------------- 
      String#<<  2.345M (± 7.2%) i/s -  11.761M in 5.041164s 
    String interpolate  1.242M (± 5.4%) i/s -  6.325M in 5.108324s 

Comparison: 
      String#<<: 2344530.4 i/s 
    String interpolate: 1241784.9 i/s - 1.89x slower 

Tại một đoán, tôi muốn nói suy mà tạo ra một chuỗi tạm thời đó là lý do tại sao nó chậm hơn.

Các vấn đề liên quan