It's common to need to join strings, and in Ruby we have common ways of doing it: appending, concatenating and interpolating one into the other, or using the built-in concat method in String. (We have multiple ways of doing it for flexibility and to ease the transition from other languages to Ruby.)
Starting with:
'a ' << 'z' # => "a z"
'a '.concat('z') # => "a z"
'a ' + 'z' # => "a z"
"a #{'z'}" # => "a z"
Assuming we don't want to change either string and that the strings won't be assigned to variables, what is the fastest way to join them, and does the fastest way change as the size of the "left" string grows?
For those who can't figure out why we'd post questions like this, it's to help educate and show the most efficient way to do a particular task. Newcomers to a language, Ruby in this case, often drag old ways of doing something with them, and inadvertently write code that runs more slowly than necessary. A simple change to their coding style can result in faster code.
Starting with short strings:
z = 'z'
'a ' << z # => "a z"
'a '.concat(z) # => "a z"
'a ' + z # => "a z"
"a #{z}" # => "a z"
require 'fruity'
compare do
append { 'a ' << z}
concat { 'a '.concat(z)}
plus { 'a ' + z}
interpolate { "a #{z}" }
end
# >> Running each test 65536 times. Test will take about 2 seconds.
# >> interpolate is similar to append
# >> append is similar to plus
# >> plus is faster than concat by 2x ± 0.1
Increasing the "left" string to 11 characters:
require 'fruity'
compare do
append { 'abcdefghij ' << z}
concat { 'abcdefghij '.concat(z)}
plus { 'abcdefghij ' + z}
interpolate { "abcdefghij #{z}" }
end
# >> Running each test 65536 times. Test will take about 2 seconds.
# >> interpolate is similar to append
# >> append is similar to plus
# >> plus is faster than concat by 2x ± 1.0
51 characters:
compare do
append { 'abcdefghijabcdefghijabcdefghijabcdefghijabcdefghij ' << z}
concat { 'abcdefghijabcdefghijabcdefghijabcdefghijabcdefghij '.concat(z)}
plus { 'abcdefghijabcdefghijabcdefghijabcdefghijabcdefghij ' + z}
interpolate { "abcdefghijabcdefghijabcdefghijabcdefghijabcdefghij #{z}" }
end
# >> Running each test 32768 times. Test will take about 2 seconds.
# >> plus is faster than append by 2x ± 1.0
# >> append is similar to interpolate
# >> interpolate is similar to concat
101:
compare do
append { 'abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij ' << z}
concat { 'abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij '.concat(z)}
plus { 'abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij ' + z}
interpolate { "abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij #{z}" }
end
# >> Running each test 32768 times. Test will take about 2 seconds.
# >> plus is faster than interpolate by 2x ± 0.1
# >> interpolate is similar to append
# >> append is similar to concat
501:
compare do
append { 'abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij ' << z}
concat { 'abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij '.concat(z)}
plus { 'abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij ' + z}
interpolate { "abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij #{z}" }
end
# >> Running each test 16384 times. Test will take about 1 second.
# >> plus is faster than append by 2x ± 0.1
# >> append is similar to interpolate
# >> interpolate is similar to concat
Once the strings got past 50 characters + consistently outperformed the others.
In the comments there are mention of some of these mutating the string on the left. Here's what would happen if it was a variable on the left, not a literal string:
a = 'a'
z = 'z'
a << z # => "az"
a # => "az"
a = 'a'
a.concat(z) # => "az"
a # => "az"
compared to:
a + z # => "az"
a # => "a"
"#{a} #{z}" # => "a z"
a # => "a"
Note: The initial version of answer had a bad test using:
"a #{'z'}"
The problem with that is Ruby is smart enough to recognize that 'z' is another literal and converts the string into:
"a z"
with the end result that the test would be unfairly faster than the others.
It's been a while and Ruby's smarter and faster. I added a couple additional tests:
puts "Running Ruby v%s" % RUBY_VERSION
require 'fruity'
z_ = 'z'
compare do
append { 'abcdefghij ' << 'z' }
concat { 'abcdefghij '.concat('z') }
plus { 'abcdefghij ' + 'z' }
interpolate1 { "abcdefghij #{'z'}" }
interpolate2 { "abcdefghij #{z_}" }
adjacent { 'abcdefghij' ' z' }
end
# >> Running Ruby v2.7.0
# >> Running each test 65536 times. Test will take about 3 seconds.
# >> adjacent is similar to interpolate1
# >> interpolate1 is faster than interpolate2 by 2x ± 1.0
# >> interpolate2 is similar to append
# >> append is similar to concat
# >> concat is similar to plus
interpolate1 and adjacent are basically the same as far as the interpreter is concerned and will be concatenated prior to running. interpolate2 forces Ruby to do it at run-time so it's a little slower.
I was browsing some code and spotted this:
stem = ""
answer = ""
return if stem.nil? || answer.nil? || \
stem.question == answer.question
What is the \ for? I know \ is used in strings, but I've never seen a use-case for this before. Is this a syntax error or some advanced ruby syntax? Am I missing something?
It's a useless line-continuation character.
The question "is it a syntax error" seems pretty simple to discover.
\ is used to indicate line continuation in ruby. Using \ will strip the \n (newline) character.
Example (Using string):
Without \:
2.1.2-perf :018 > s = "test this
2.1.2-perf :019"> out"
=> "test this\nout"
With \:
2.1.2-perf :020 > s = "test this \
2.1.2-perf :021"> out"
=> "test this out"
Example (without using string):
Without \:
2.1.2-perf :043 > return "test" if true && false &&
2.1.2-perf :044 > true
=> nil
With \:
2.1.2-perf :045 > return "test" if true && false && \
2.1.2-perf :046 > true
=> nil
In your case, it wouldn't matter, but it is not a syntax error.
From the doc:
Ruby programs are sequence of expressions. Each expression are delimited by semicolons(;) or newlines. Backslashes at the end of line does not terminate expression.
I am having text file t.txt,I want to calculate sum of all the digits in text file
Example
--- t.txt ---
The rahul jumped in 2 the well. The water was cold at 1 degree Centigrade. There were 3 grip holes on the walls. The well was 17 feet deep.
--- EOF --
sum 2+1+3+1+7
My ruby code to calculate sum is
ruby -e "File.read('t.txt').split.inject(0){|mem, obj| mem += obj.to_f}"
But i am not getting any answer??
str = "The rahul jumped in 2 the well. The water was cold at 1 degree Centigrade. There were 3 grip holes on the walls. The well was 17 feet deep."
To get sum of all integers:
str.scan(/\d+/).sum(&:to_i)
# => 23
Or to get sum of all digits as in your example:
str.scan(/\d+?/).sum(&:to_i)
# => 14
PS: I used sum seeing Rails tag. If you are only using Ruby you can use inject instead.
Example with inject
str.scan(/\d/).inject(0) { |sum, a| sum + a.to_i }
# => 14
str.scan(/\d+/).inject(0) { |sum, a| sum + a.to_i }
# => 23
Your statement is computing correctly. Just add puts before File read as:
ruby -e "puts File.read('t.txt').split.inject(0){|mem, obj| mem += obj.to_f}"
# => 23.0
For summing single digit only:
ruby -e "puts File.read('t.txt').scan(/\d/).inject(0){|mem, obj| mem += obj.to_f}"
# => 14.0
Thanks
I have two numbers of different length:
"103" and "11"
In irb:
2.1.1 :005 > "11" > "103"
=> true
2.1.1 :006 > "11" < "103"
=> false
Why does this happen? I understand I can to a .to_i for each string, but if this is a rails query where the column type is string, anything I can do about this?
Strings are sorted lexicographically which means that "1" comes after "0", and "103" comes before "11", and before "1122344", and before "1abc".
You cannot compare strings as if they were numbers, you need to parse them as numbers before you can do that.
The only way I can think of, is to make sure they are padded with enough zeroes before they are turned into a string: "000103", "000011"...
Strings are being compared character by character. Hence '11' > '103' execution stops on a second character and returns true, since '1'.chr > '0'.chr
They are strings. And they are compared by String#ord value.
So '1'.ord # => 49 and '0'.ord # => 48. That is why
'11' > '10' # => true
# and
'11' > '100' # => true
as well as
'b' > 'a' # => true
'a'.ord # => 97
'b'.ord # => 98
# and
'b' > 'aaaaa' # => still true
In PHP you can do:
print_r($var) or vardump($var)
which prints "human-readible" information about variable.
Is there equivalent functions / helpers for those in Ruby / Rails ?
In Rails templates you can do
<%= debug an_object %>
and it will do nice HTML PRE output.
Try using pp.
You will need to require it in scripts (or in irb if your .irbc doesn't already do this):
require 'pp'
Then you can 'PrettyPrint' an object thus:
pp object
Instead of requiring 'pp' and using pp, you can simply do
p object
Tested example
require 'pp'
class A
def initialize
#a = 'somevar'
#b = [1,2,3]
#c = {'var' => 'val'}
end
end
a = A.new
pp a # Gives -> #<A:0x2c6d048 #a="somevar", #b=[1, 2, 3], #c={"var"=>"val"}>
p a # Gives -> #<A:0x2c6d048 #a="somevar", #b=[1, 2, 3], #c={"var"=>"val"}>. No need to require 'pp'
There's the method inspect which helps. Sometimes calling the to_s method on an object will help (to_s returns a string representation of the object). You can also query methods, local_variables, class_variables, instance_variables, constants and global_variables.
p ['Hello',"G'day",'Bonjour','Hola'].inspect
# >> "[\"Hello\", \"G'day\", \"Bonjour\", \"Hola\"]"
p ['Hello',"G'day",'Bonjour','Hola'].to_s
# >> "HelloG'dayBonjourHola"
p Array.new.methods
# >> ["select", "[]=", "inspect", "compact"...]
monkey = 'baboon'
p local_variables
# >> ["monkey"]
class Something
def initialize
#x, #y = 'foo', 'bar'
##class_variable = 'gorilla'
end
end
p Something.class_variables
# >> ["##class_variable"]
s = Something.new
p s.instance_variables
# >> ["#x", "#y"]
p IO.constants
# >> ["TRUNC", "SEEK_END", "LOCK_SH"...]
p global_variables
# >> ["$-d", "$\"", "$$", "$<", "$_", "$-K"...]
I know this is an old post, but it is the first thing that Google pops up when searching for "Ruby equivalent of PHP print_r". I'm using Ruby in the command line mode, and there's really not a very good equivalent. "pp" is ok for fairly simple structures, but as soon as you start nesting hashes in arrays in hashes in more arrays, it turns into a jumble pretty fast. Since I haven't found a good emulation of print_r, I wrote one myself. It's good enough for my purposes, not overly complicated and I thought I'd share it to save other people some headache. Compare the output with the real PHP print_r
def print_r(inHash, *indent)
#indent = indent.join
if (inHash.class.to_s == "Hash") then
print "Hash\n#{#indent}(\n"
inHash.each { |key, value|
if (value.class.to_s =~ /Hash/) || (value.class.to_s =~ /Array/) then
print "#{#indent} [#{key}] => "
self.print_r(value, "#{#indent} ")
else
puts "#{#indent} [#{key}] => #{value}"
end
}
puts "#{#indent})\n"
elsif (inHash.class.to_s == "Array") then
print "Array\n#{#indent}(\n"
inHash.each_with_index { |value,index|
if (value.class.to_s == "Hash") || (value.class.to_s == "Array") then
print "#{#indent} [#{index}] => "
self.print_r(value, "#{#indent} ")
else
puts "#{#indent} [#{index}] => #{value}"
end
}
puts "#{#indent})\n"
end
# Pop last indent off
8.times {#indent.chop!}
end
Here's an example (made messy on purpose to show why the PHP print_r is so nice):
carTools = [ "Socket Set", "Combination Wrenches", "Oil Filter puller", "Brake Compressor" ]
houseTools =[ "Circular Saw", "Miter Saw", "Drill" ]
garageItems = Hash["Car1" => "Ford Mustang", "Car2" => "Honda Civic", "Bike1" => "IronHorse"]
garageItems["Tools"] = Hash["Car Tools" => carTools, "House Tools" => houseTools]
constructionSupplies = Hash["Plywood" => ["3/4\" T&G Plywood Sheets", "1/2\" Plywood Sheets"],
"Boards" => ["2x4s", "2x6s", "Engineered I-Joists"],
"Drywall" => ["4x8 1/2\" Sheetrock", "Mesh tape", "Paper tape", "Joint compount"]]
carParts = Hash["Mustang" => ["Clutch", "Transmission", "3.55 Ring & Pinion Gears", "Differential", "30# Injectors", "Pro-M 77mm MAF"]]
garageItems["Supplies"] = ["Oil", "WD40", constructionSupplies, carParts, "Brake Fluid"]
print_r(garageItems)
Output of print_r (actually comprehensible by a human):
Hash
(
[Car1] => Ford Mustang
[Car2] => Honda Civic
[Bike1] => IronHorse
[Tools] => Hash
(
[Car Tools] => Array
(
[0] => Socket Set
[1] => Combination Wrenches
[2] => Oil Filter puller
[3] => Brake Compressor
)
[House Tools] => Array
(
[0] => Circular Saw
[1] => Miter Saw
[2] => Drill
)
)
[Supplies] => Array
(
[0] => Oil
[1] => WD40
[2] => Hash
(
[Plywood] => Array
(
[0] => 3/4" T&G Plywood Sheets
[1] => 1/2" Plywood Sheets
)
[Boards] => Array
(
[0] => 2x4s
[1] => 2x6s
[2] => Engineered I-Joists
)
[Drywall] => Array
(
[0] => 4x8 1/2" Sheetrock
[1] => Mesh tape
[2] => Paper tape
[3] => Joint compount
)
)
[3] => Hash
(
[Mustang] => Array
(
[0] => Clutch
[1] => Transmission
[2] => 3.55 Ring & Pinion Gears
[3] => Differential
[4] => 30# Injectors
[5] => Pro-M 77mm MAF
)
)
[4] => Brake Fluid
)
)
Check out the guide for debugging rails:
http://guides.rubyonrails.com/debugging_rails_applications.html
hints:
script/console is great to try stuff in the context of your app
script/server --debugger to start the server with a debugger turned on, you can then use 'debug' in your code to break into an interactive shell
One approach I lean on a lot is this:
logger.debug "OBJECT: #{an_object.to_yaml}"
Easy to read, although it can get a little unwieldy for large objects.
Guess I'm a little late to this, but what about logger.info [debug|warning]? Use this from Controllers and Models. It will show up in your log files (development.log when in dev mode); and the above mentioned <%= debug("str: " + str) %> for views.
These aren't exact answers to your questions but you can also use script/console to load your rails app in to an interactive session.
Lastly, you can place debugger in a line of your rails application and the browser will "hang" when your app executes this line and you'll be able to be in a debug session from the exact line your placed your debugger in the source code.