Ruby lets me do:
list = [1,2,3]
puts "%s %s" % list
and returns 1 2. What if I want to skip the second element (to print 1 3)? Yes I know it's easily doable without string formatting, but for my specific case I want to know if it's possible using string formatting.
puts "%1$s %3$s" % list
........
"%s %0.s%s" % [1,2,3]
#=> "1 3"
The decimal point tells Ruby that 0 is the field width rather than a flag. You could also write %0.0s.
You can do something like this:
list = [1,2,3]
puts "%s %s" % list.values_at(0,2)
Related
def factors_to_three (n)
puts n
if n % 3 == 0
puts "Your number is divisible by 3"
else
puts "Your Number is NOT divisible by 3"
end
end
puts "Enter the number to check if its divisible by 3"
number = gets.chomp
factors_to_three(number)
No matter what number I input, my program always outputs Your Number is NOT divisible by 3, even when clearly is.
n is not an integer. gets() returns a string and chomp removes the newline, but the data is still a string.
"6" % 3 != 0
6 % 3 == 0
You need to convert your incoming data to an integer representation.
Your result will always be false because gets.chomp returns a String:
number = gets.to_i
The above code will work but you must always type an integer. There are better ways to manage checking to see if the input is valid.
So you could check first like this:
number = gets
factors_to_three(number.to_i) if number.is_a?(Integer)
When text is read using gets, it is read in as a string. So in your code, number is actually not a number, but a string. Because of this, the "modulus" operator is in fact not the modulus operator, but the format operator on String, String#%:
Format—Uses str as a format specification, and returns the result of applying it to arg. If the
format specification contains more than one substitution, then arg
must be an Array or Hash containing the values to be substituted. See
Kernel::sprintf for details of the format string.
"%05d" % 123 #=> "00123"
"%-5s: %08x" % [ "ID", self.object_id ] #=> "ID : 200e14d6"
"foo = %{foo}" % { :foo => 'bar' } #=> "foo = bar"
As you can see, this method returns a string, which does not equal zero. Therefore, this program will always say that the number is not divisible by 3, even when it is.
You can fix this by calling to_i on the input returned from get:
number = gets.chomp.to_i
I was going through some piece of code when I found this line
if ('%{test}' % {:test => 'replaced'} == 'replaced')
# If this works, we are all good to go.
Why is '%{test}' % {:test => 'replaced'} returning value "replaced"? What exactly is % doing over here?
That is doing "interpolation". The value "replaced" of the key :test of the hash is inserted to the %{test} position in the original string '%{test}'.
The % can take a string, array, or hash depending on the need. When you only have a single slot in the template as in this case, it is better to use %s and pass a string like
"%s" % "replaced"
With the particular example, it is not useful.
It becomes useful when you want to replace a part of a string.
For example, if you want to generate a series of strings:
"Hello World", "Hey World", "Bye World"
you can have a template string s = "%s World" and interpolate things into it like
s % "Hello"
s % "Hey"
s % "Bye"
I have many strings following a certain pattern:
string = "Hello, #name. You did #thing." # example
Basically, my strings are a description where #word is dynamically. I need to replace each with a value at runtime.
string = "Hello, #{#name}. You did #{#thing}." # Is not an option!
The #word is basically a variable, but I just cannot use the method above.
How should I do that?
Instead doing search/replace, you can use Kernel#sprintf method, or its % shorthand. Combined with Hashes, it can come pretty handy:
'Hello, %{who}. You did %{what}' % {:who => 'Sal', :what => 'wrong'}
# => "Hello, Sal. You did wrong"
The advantage of using Hash instead of Array is that you don't have to worry about the ordering, and you can have the same value inserted on multiple places in the string.
You can format your string with placeholders that can be switched out dynamically using String's % operator.
string = "Hello, %s. You did %s"
puts string % ["Tony", "something awesome"]
puts string % ["Ronald", "nothing"]
#=> 'Hello, Tony. You did something awesome'
#=> 'Hello, Ronald. You did nothing'
Possible use case: Let's say you were writing a script that would be taking the name and action in as parameters.
puts "Hello, %s. You did %s" % ARGV
Assuming 'tony' and 'nothing' were the first two parameters, you would get 'Hello, Tony. You did nothing'.
This may be a really simple regex but its one of those problems that have proven hard to google.
I have error codes coming back from a third party system. They are supposed to be in the format:
ZZZ##
where Z is Alpha and # is numeric. They are supposed to be 0 padded, but i'm finding that sometimes they come back
ZZZ#
without the 0 padding.
Anyone know how i could add the 0 padding so i can use the string as an index to a hash?
Here's my take:
def pad str
number = str.scan(/\d+/).first
str[number] = "%02d" % number.to_i
str
end
6.times do |n|
puts pad "ZZZ#{7 + n}"
end
# >> ZZZ07
# >> ZZZ08
# >> ZZZ09
# >> ZZZ10
# >> ZZZ11
# >> ZZZ12
Reading:
String#[]=
Kernel#sprintf and formatting flags.
fixed = str.gsub /([a-z]{3})(\d)(?=\D|\z)/i, '\10\2'
That says:
Find three letters
…followed by a digit
…and make sure that then you see either a non-digit or the end of file
and replace with the three letters (\1), a zero (0), and then the digit (\2)
To pad to an arbitrary length, you could:
# Pad to six digits
fixed = str.gsub /([a-z]{3})(\d+)/i do
"%s%06d" % [ $1, $2.to_i ]
end
Here's mine:
"ZZZ7".gsub(/\d+/){|x| "%02d" % x}
=> "ZZZ07"
There's probably a million ways to do this but here's another look.
str.gsub!(/[0-9]+/ , '0\0' ) if str.length < 5
I am trying to create a program where the first three characters of a string is repeated a given number of times like this:
foo('Chocolate', 3) # => 'ChoChoCho'
foo('Abc', 3) # => 'AbcAbcAbc'
I know I can use length to count characters, but how do I specify the length of the string to be outputted? Also how can I specify the number of times?
def foo(str, n)
str[0..2] * n
end
You can use something like this.
def print_first_three_x_times(string, x)
#remove everything but the first three chars
string.slice!(3..string.length)
#print x times
x.times{ print string }
end
output:
Hunter#Hunter-PC ~
$ irb
irb(main):008:0> print_first_three_x_times("Hunter",5)
HunHunHunHunHun=> 5
irb(main):009:0>