আমি রুবিতে আরও বেশি মার্জিত উপায়ের সন্ধান করছি।
আমার নিচের লাইনটি রয়েছে:
source = "#{ROOT_DIR}/" << project << "/App.config"
এটি করার একটি সুন্দর উপায় আছে?
এবং এই ক্ষেত্রে <<
এবং মধ্যে পার্থক্য কি +
?
আমি রুবিতে আরও বেশি মার্জিত উপায়ের সন্ধান করছি।
আমার নিচের লাইনটি রয়েছে:
source = "#{ROOT_DIR}/" << project << "/App.config"
এটি করার একটি সুন্দর উপায় আছে?
এবং এই ক্ষেত্রে <<
এবং মধ্যে পার্থক্য কি +
?
উত্তর:
আপনি এটি বিভিন্ন উপায়ে করতে পারেন:
<<
তবে এটি সাধারণ উপায় নয়স্ট্রিং বিরতি সহ
source = "#{ROOT_DIR}/#{project}/App.config"
সঙ্গে +
source = "#{ROOT_DIR}/" + project + "/App.config"
দ্বিতীয় পদ্ধতিটি আমি যা দেখেছি তার থেকে স্মৃতি / গতির মেয়াদে আরও দক্ষ বলে মনে হচ্ছে (যদিও এটি মাপা হয়নি)। ROOT_DIR শূন্য হলে এই তিনটি পদ্ধতিই একটি অবিচ্ছিন্ন ধ্রুবক ত্রুটি ফেলবে।
পথের নামগুলি নিয়ে কাজ করার সময়, আপনি File.join
পথের নাম পৃথককারীকে নিয়ে ঝামেলা এড়াতে ব্যবহার করতে পারেন want
শেষ পর্যন্ত এটি স্বাদের বিষয়।
+
অপারেটর স্বাভাবিক সংযুক্তকরণের পছন্দ, এবং সম্ভবত 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"
+
এবং <<
প্রায় একই রকম হতে চলেছে। আপনি যদি অনেকগুলি স্ট্রিং, বা সত্যিই বড়গুলি নিয়ে কাজ করে থাকেন তবে আপনি একটি পার্থক্য লক্ষ্য করতে পারেন। তারা কীভাবে অনুরূপ অভিনয় করে আমি অবাক হয়েছিলাম। gist.github.com/2895311
5.times do ... end
প্রতিটি দোভাষীর জন্য পরীক্ষার স্যুটটি বেশ কয়েকবার চালিত করেন (একই প্রক্রিয়াতে - সুতরাং একটি ব্লক বলে সমস্ত কিছু মোড়ানো ), আপনি আরও সঠিক ফলাফল দিয়ে শেষ করতে পারেন। আমার পরীক্ষাটি দেখিয়েছে যে সমস্ত রুবি ইন্টারপ্রেটারে জুড়ে ইন্টারপোলেশনটি দ্রুততম পদ্ধতি। আমি <<
দ্রুততম হওয়ার আশা করতাম , তবে সে কারণেই আমরা বেঞ্চমার্ক করব।
থেকে http://greyblake.com/blog/2012/09/02/ruby-perfomance-tricks/
<<
উফ ব্যবহার করা 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)
উপসংহার: এমআরআই-তে প্রসারণ ভারী।
আমি পথের নাম ব্যবহার করতে পছন্দ করব:
require 'pathname' # pathname is in stdlib
Pathname(ROOT_DIR) + project + 'App.config'
প্রায় <<
এবং+
রুবি ডক্স থেকে:
+
: নতুন ফিরিয়ে দেয় স্ট্রমে সংশ্লেষিত অন্যান্য_স্ট্রির সমন্বিত স্ট্রিং প্রদান করে
<<
: প্রদত্ত বস্তুকে স্ট্রিমের সাথে সংযুক্ত করে। যদি 0 এবং 255 এর মধ্যে অবজেক্টটি ফিক্সনাম হয় তবে এটি কনটেনটেশনের আগে একটি অক্ষরে রূপান্তরিত হয়।
সুতরাং পার্থক্যটি প্রথম অপারেন্ডে পরিণত হয় ( <<
স্থান পরিবর্তন করে, +
নতুন স্ট্রিং ফিরিয়ে দেয় যাতে এটি মেমরির ভারী হয়) এবং যদি প্রথম অপারেন্ড ফিকনাম হয় তবে কী হবে ( <<
সংখ্যার সমান কোডযুক্ত অক্ষরের সাথে যুক্ত +
হবে, উত্থাপন করবে) ত্রুটি)
Pathname('/home/foo') + '/etc/passwd' # => #<Pathname:/etc/passwd>
। এটি রুবডোক উদাহরণের উপর ভিত্তি করে ডিজাইন দ্বারা। ফাইল.জয়িন নিরাপদ বলে মনে হচ্ছে।
(Pathname(ROOT_DIR) + project + 'App.config').to_s
যদি স্ট্রিং অবজেক্টটি ফিরিয়ে দিতে চান তবে আপনাকে কল করতে হবে ।
আমাকে তার সাথে আমার সমস্ত অভিজ্ঞতা আপনাকে দেখাতে দিন।
আমার কাছে একটি কোয়েরি ছিল যা 32 কে রেকর্ড ফিরিয়েছিল, প্রতিটি রেকর্ডের জন্য আমি সেই পদ্ধতিটি ডেকেছিলাম যে ডাটাবেস রেকর্ডটিকে একটি কাঠামোযুক্ত স্ট্রিংয়ে ফর্ম্যাট করার জন্য এবং এটি একটি স্ট্রিংয়ের সাথে যুক্ত করে যে এই সমস্ত প্রক্রিয়া শেষে ডিস্কে একটি ফাইলে পরিণত হবে।
আমার সমস্যাটি ছিল রেকর্ডটি পেরিয়ে, প্রায় 24k এর মধ্যে, স্ট্রিংকে সংযুক্ত করার প্রক্রিয়াটি একটি ব্যথা চালু করে।
আমি নিয়মিত '+' অপারেটরটি ব্যবহার করে এটি করছিলাম।
আমি যখন '<<' এ পরিবর্তিত হয়েছি তখন ম্যাজিকের মতো ছিল। সত্যিই দ্রুত ছিল।
সুতরাং, আমি আমার পুরানো সময়গুলি মনে করি - 1998 এর সাজান - যখন আমি জাভা ব্যবহার করছিলাম এবং স্ট্রিংকে '+' ব্যবহার করে স্ট্রিংব্রফার (এবং এখন আমরা, জাভা বিকাশকারীদের স্ট্রিংবিল্ডার) রেখেছি।
আমি বিশ্বাস করি যে রুবি বিশ্বে + / << প্রক্রিয়াটি জাভা বিশ্বে + / স্ট্রিংবিল্ডার.অ্যাপেন্ডের মতো।
প্রথম স্মৃতিতে পুরো অবজেক্টটিকে পুনরায় গণনা করুন এবং অন্যটি একটি নতুন ঠিকানার দিকে নির্দেশ করুন।
কনটেনটেশন আপনি বলছেন? তাহলে কীভাবে #concat
পদ্ধতি?
a = 'foo'
a.object_id #=> some number
a.concat 'bar' #=> foobar
a.object_id #=> same as before -- string a remains the same object
সমস্ত ন্যায্যতা concat
হিসাবে , aliesated হয় <<
।
"foo" "bar" 'baz" #=> "foobarabaz"
এটি করার আরও উপায় এখানে রয়েছে:
"String1" + "String2"
"#{String1} #{String2}"
String1<<String2
এবং আরও ...
আপনি ব্যবহার করতে পারেন +
বা <<
অপারেটর রাখতে পারেন , তবে রুবি .concat
ফাংশনে সবচেয়ে বেশি পছন্দনীয় কারণ এটি অন্যান্য অপারেটরের তুলনায় অনেক দ্রুত। আপনি এটি ব্যবহার করতে পারেন।
source = "#{ROOT_DIR}/".concat(project.concat("/App.config"))
.
আপনার শেষ concat
নং পরে একটি অতিরিক্ত আছে ?
পরিস্থিতি সম্পর্কিত বিষয়গুলি উদাহরণস্বরূপ:
# this will not work
output = ''
Users.all.each do |user|
output + "#{user.email}\n"
end
# the output will be ''
puts output
# this will do the job
output = ''
Users.all.each do |user|
output << "#{user.email}\n"
end
# will get the desired output
puts output
প্রথম উদাহরণে, +
অপারেটরের সাথে সম্মিলিতভাবে output
অবজেক্টটি আপডেট হবে না , তবে দ্বিতীয় উদাহরণে <<
অপারেটর output
প্রতিটি পুনরাবৃত্তির সাথে অবজেক্টটি আপডেট করবে । সুতরাং, উপরের ধরণের পরিস্থিতিটি <<
আরও ভাল।
আপনার নির্দিষ্ট ক্ষেত্রে আপনি Array#join
ফাইল পাথ ধরণের স্ট্রিং তৈরি করার সময়ও ব্যবহার করতে পারেন :
string = [ROOT_DIR, project, 'App.config'].join('/')]
বিভিন্ন ধরণের স্ট্রাইটে স্বয়ংক্রিয়ভাবে রূপান্তরিত করার এটির একটি মনোরম পার্শ্ব প্রতিক্রিয়া রয়েছে:
['foo', :bar, 1].join('/')
=>"foo/bar/1"