Ruby has a data type not often seen in other programming languages, and that’s the symbol. Symbols are similar to strings in that they are made of characters, but instead of being surrounded by quotes, symbols are prefixed with a colon
:name
Symbols are typically used as identifiers.
<=> return -1 if x < y return 0 if x = y return 1 if x > y
a.sort { |x, y| x <=> y }
x ||= 6 # assign 6 if x is nil or false
p a; p b; p c; p d; p e
(p is a shorthand of print)
Strings are objects of the String class
my_string = "Hello." # create a string from a literal
my_empty_string = String.new # create an empty string
my_copied_string = String.new(my_string) # copy a string to a new variable
With encoding
str = "With ♥!"
print("My String's encoding: ", str.encoding.name)
print("\nMy String's size: ", str.size)
print("\nMy String's bytesize: ", str.bytesize)
Some more actions
str[0,4] # first four characters
str[str.size, 0] = " World!" # append by assigning at the end of the string
str[5, 0] = "," # insert a comma after the 5th position
str[5, 6] = "" # delete 6 characters starting from index 5.
str[5,1] = " World" # replace the string starting from index 5 and of length 1 with the given string.
puts "Hi" * 3 # "HiHiHi"
With long string and free of escape characters, use this format
document = <<-HERE # We begin with <<- followed by the ending delimiter HERE
This is a string literal.
It has two lines and abruptly ends with a newline...
HERE
Chomp
> "Hello World! \r\n".chomp
"Hello World! "
> "Hello World!".chomp("orld!")
"Hello W"
> "hello \n there".chomp
"hello \n there"
Strip
> " hello ".strip
"hello"
> "\tgoodbye\r\n".strip
"goodbye"
Chop: Returns a new string with the last character removed. Note that carriage returns (\n, \r\n) are treated as single character
> "string\n".chop
"string"
> "string".chop
"strin"
arr.map(&:strip).join(' ')
Include
> "hello".include? "lo" #=> true
Gsub: String.gsub(pattern, <hash|replacement>)
"hello".gsub(/[aeiou]/, '*') #=> "h*ll*"
"hello".gsub(/([aeiou])/, '') #=> "hll"
print "Hello #{name}"
money.each_char {|x| p x} # prints each character
money.each_byte {|x| p x} # first char represented by two bytes
money.each_line {|line| p line}
. Passing blocks is one way to pass functions as arguments to other functions. . Blocks are not objects, and they can't be saved to variables. https://www.hackerrank.com/challenges/ruby-blocks/problem
def call_block
print "start"
yield
print "end"
end
call_block do
print "inside"
end
def calculate(a, b)
yield(a, b)
end
print calculate(15, 10) {|a, b| a-b}
Define a hash
h = Hash.new
h = Hash.new(1) # key = 1
h = {"simple" => 1, "complex" => 2}
h["simple"] = 1
manipulate
h.store(key, value) # is identical to h[key] = value
h.delete(key)
h.keep_if {|key, value| key % 2 == 0}
h.delete_if {|key, value| key % 2 == 0}
get keys, values
h.keys
h.values
merge
> another_guy.merge job: "none"
=> {:name=>"Ben", :age=>20, :job=>"none"}
loop through a hash
h.each do |key, value|
# codes
end
h.each do |arr|
# arr[0] is key, arr[1] is value
end
a = Array.new
a = []
a = Array.new(1) # initialize with one nil element
a = [nil]
a = Array.new(2, 10) # array of 2 elements with value 10
a[0]
a.at[0]
a[1..3]
a[1...3] # last index is excluded
a[1, 4] # start index is 1 and 4 is length of range
a[-1] # last element
a.first
a.first(10)
a.last
a.take(3) # take 3 first elements
a.drop(3) # every elements but 3 first elements
a.push(1)
a << 1
a.insert(2, 2.5) # insert at index 2
a.unshift(1, 2, 3) # insert some elements at the start of array
a.pop # delete an element from the end of the array
a.shift # delete first element
a.delete_at(2)
arr.delete(5) # delete all occurrences of a given element
> list + [4, 5, 6]
=> [1, 2, 3, 4, 5, 6]
Filter
arr.select{|a| a > 2}
arr.reject{|a| a > 2}
a.keep_if {|a| a % 2 == 0}
a.delete_if {|a| a % 2 == 0}
Check present or none of element
sentences = [[]]
if sentences.first.present?
if sentences.first.none?
# Returns +text+ wrapped at +len+ columns and indented +indent+ spaces.
# By default column length +len+ equals 72 characters and indent
# +indent+ equal two spaces.
#
# my_text = 'Here is a sample text with more than 40 characters'
#
# format_paragraph(my_text, 25, 4)
# # => " Here is a sample text with\n more than 40 characters"
def format_paragraph(text, len = 72, indent = 2)
sentences = [[]]
text.split.each do |word|
if sentences.first.present? && (sentences.last + [word]).join(' ').length > len
sentences << [word]
else
sentences.last << word
end
end
indentation = " " * indent
sentences.map! { |sentence|
"#{indentation}#{sentence.join(' ')}"
}.join "\n"
end
#map!
to join the words with a space
Transpose to convert row into column
a = [1, 2, 3]
b = [4, 5, 6]
c = [7, 8, 9]
[a, b, c].transpose.map { |x| x.reduce :+ }
# => [12, 15, 18]
Proc objects are blocks of code that can be bound to a set of local variables. You can think of a proc object as a "saved" block. https://www.hackerrank.com/challenges/ruby-procs/problem
def foo(a, b, my_proc)
my_proc.call(a, b)
end
add = proc {|x,y| x + y}
foo(10, 20, add)
(which is especially useful for enumerations) https://stackoverflow.com/questions/9429819/what-is-the-functionality-of-operator-in-ruby
my_array = gets.split().map(&:to_i)
# is identical to (&
my_array = gets.split().map(|a| a.to_i)
my_proc = Proc.new { puts "foo" }
my_method_call(&my_proc) # is identical to:
my_method_call { puts "foo" }
http://flats.github.io/blog/2015/12/02/getting-to-know-rubys-map-and-reduce/
toppings = %w(perpperoni mushroom bacon)
def pizza(toppings)
toppings.map do |topping|
"I love #{topping} pizza"
end
end
# => return array of strings
ROT 13 encrypt/decrypt: https://www.hackerrank.com/challenges/ruby-enumerable-collect/problem
def rot13(secret_messages)
# your code here
secret_messages.map {|str|
str.split('').map {|c|
if c.between?('A', 'M') or c.between?('a', 'm')
(c.ord+13).chr
elsif c.between?('N', 'Z') or c.between?('n', 'z')
(c.ord-13).chr
else
c
end
}.join('')
}
end
http://flats.github.io/blog/2015/12/02/getting-to-know-rubys-map-and-reduce/
reduce
(or inject
) returns a value that is the result of applying a binary operation to the return value of applying the supplied block to each element of the enumerable. Whoa. What a mouthful. In other words, #reduce “reduces” each element of an enumerable to a single value, accumulates that value in a single variable, and then returns the value of the accumulator.
array = [1, 2, 3, 4] # => [1, 2, 3, 4]
array.reduce(0, :+) => 10
is the same as detail form
array.reduce(0) { |sum, element| sum + element } # => 10 with initial value is 0
If you don’t declare an initial value, the initial value will be the first element of the collection.
Inject
module_name = "X::Y::Z"
module_name.split('::').inject([]) { |memo,x| memo.unshift(memo.empty? ? x : "#{memo[0]}::#{x}") }
=> ["X::Y::Z", "X::Y", "X"]
sum of an array
return a.inject :+
The same as map
but it is used for hashes. Collect imtes into an array
>>> [1,2,3].map { |x| 2*x }
=> [2, 4, 6]
>>> {:a=>1, :b=>2, :c=>3}.collect { |key, value| 2*value }
=> [2, 4, 6]
when you write
def hello_world
'Eha! Ruby'
end
You are essentially adding a private method to Object
class
class Object
private
def hello_world2
'Eha! Ruby'
end
end
These methods, unlike functions in other object oriented programming language (e.g., Python) are not a first-class citizens, because they cannot be passed to other methods as arguments, returned by other methods, or assigned to variables.
Method arguments Default value
def take(arr, omit=1)
Multiple arguments
def take(arr, *rest)
Hash arguments
def fetch_file(uri, options)
if options.has_key?(:proxy)
# do something
end
end
def foo(x, str: "foo", num: 424242)
[x, str, num]
end
foo(13) #=> [13, 'foo', 424242]
foo(13, str: 'bar') #=> [13, 'bar', 424242]
def foo(str: "foo", num: 424242, **options)
[str, num, options]
end
foo #=> ['foo', 424242, {}]
foo(check: true) # => ['foo', 424242, {check: true}]
https://www.hackerrank.com/challenges/ruby-lambdas/problem
Lambdas are anonymous functions. Lambdas in Ruby are objects of the class Proc.
#Ruby version <= 1.8
lambda { .... }
lambda do
....
end
#Ruby version >= 1.9, "stabby lambda" syntax is added
-> { .... }
-> do
....
end
Ruby version >= 1.9 can use both lambda and stabby lambda, ->.
Lambda that takes no arguments.
def area (l, b)
-> { l * b }
end
x = 10.0; y = 20.0
area_rectangle = area(x, y).call
area_triangle = 0.5 * area(x, y).()
puts area_rectangle #200.0
puts area_triangle #100.0
Lambda that takes one or more arguments.
area = ->(a, b) { a * b }
x = 10.0; y = 20.0
area_rectangle = area.(x, y)
area_triangle = 0.5 * area.call(x, y)
puts area_rectangle #200.0
puts area_triangle #100.0
Yes, there is difference between a proc and a lambda in Ruby. Equivalent to Proc.new, except the resulting Proc objects check the number of parameters passed when called.
https://www.hackerrank.com/challenges/ruby-closures/problem Closure is a function/method that: . Can be passed around like an object. It can be treated like a variable, which can be assigned to another variable, passed as an argument to a method. . Remembers the value of variables no longer in scope. It remembers the values of all the variables that were in scope when the function was defined. It is then able to access those variables when it is called even if they are in a different scope.
def plus_1(y)
x = 100
y.call #remembers the value of x = 1
end
x = 1
y = -> { x + 1 }
puts plus_1(y) # 2
Blocks, Procs and Lambdas are closures in Ruby.
def block_message_printer
message = "Welcome to Block Message Printer"
if block_given?
yield
end
puts "But in this function/method message is :: #{message}"
end
message = gets
block_message_printer { puts "This message remembers message :: #{message}" }
Lazy evaluation is an evaluation strategy that delays the assessment of an expression until its value is needed. Ruby 2.0 introduced a lazy enumeration feature. Lazy evaluation increases performance by avoiding needless calculations, and it has the ability to create potentially infinite data structures.
power_array = -> (power, array_size) do
1.upto(Float::INFINITY).lazy.map { |x| x**power }.first(array_size)
end
puts power_array.(2 , 4) #[1, 4, 9, 16]
puts power_array.(2 , 10) #[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
puts power_array.(3, 5) #[1, 8, 27, 64, 125]
In this example, lazy
avoids needless calculations to compute power_array
.
If we remove lazy from the above code, then our code would try to compute all x ranging from 1 to Float::INFINITY.
To avoid timeouts and memory allocation exceptions, we use lazy. Now, our code will only compute up to first(array_size).
object properties
@a
class properties
@@a
def initialize(params)
require 'forwardable'
class Results
include Enumerable
extend Forwardable
def_delegators :@result_array, :each, :<<
def initialize()
@result_array = ["Hello", "World"]
end
end
obj = Results.new()
obj.each {|a| puts a}
obj = ClassName.new
a?1 # return True or False
a.range?(1,10)
a.range?1,10
14.between?(10,20) # true
(10..20).member?(14) # true
(10..20).include?(14) # true
Used with data collections is one which groups the elements according to some evaluation result.
> (1..5).group_by {|x| x%2}
{1=>[1,3,5], 0=>[2, 4]}
def group_by_marks(marks, pass_marks)
# your code here
marks.group_by {|key, value| value >= pass_marks ? "Passed" : "Failed"}
end
One of such useful methods is each_with_index which allows you to iterate over items along with an index keeping count of the item.
> colors = ['red', 'green', 'blue']
> colors.each_with_index { |item, index| p "#{index}:#{item}" }
"0:red"
"1:green"
"2:blue"
https://www.hackerrank.com/challenges/ruby-enumerable-any-all-none-find/problem
> arr = [1, 2, 3, 4, 5, 6]
=> [1, 2, 3, 4, 5, 6]
> h = {"a" => 1, "b" => 2, "c" => 3}
=> {"a" => 1, "b" => 2, "c" => 3}
> arr.any? {|a| a % 2 == 0} # checks if any number in the array is even
=> True
> h.any? {|key, value| value.is_a? String} # checks if any value of the Hash object is of the type String
=> False
> arr.all? {|a| a.is_a? Integer} # checks if all elements of the array are of the type Integer
=> True
> h.all? {|key, value| key.is_a? String} # checks if all keys of the Hash object are of the type String
=> True
> arr.none? {|a| a.nil?} # Checks if none of the elements in the array are of nil type
=> True
> h.none? {|key, value| value < 3} # checks if all values of the Hash object are less than 3
=> False
> arr.find {|a| a > 5} # returns the first element greater than 5 and `nil` if none satisfies the condition
=> 6
> h.find {|key, value| key == "b"} # returns an Array of the first match [key, value] that satisfies the condition and nil otherwise
=> ["b", 2]
file = File.read("test.txt")
puts file