This is collection of Ruby Array methods usage, tips & tricks.
# All array method can use do..end block.
[1,2,3].each do |number|
world = "World #{number}"
puts "Hello #{world}"
end
# Curly braces block, can has multi lines too.
[1,2,3].each { |number|
world = "World #{number}"
puts "Hello #{world}"
}
# Curly braces block usually use for single line code expression,
# make it more concise, and do..end is used for readability and more explicit.
[1,2,3].each { |number| puts "Hello World #{number}" }
each
to travers all array element.
[1,2,3].each { |number| puts "Hello #{number}" }
# result:
Hello 1
Hello 2
Hello 3
NOTE: Each will return original array after finish traversing and execute the code block.
map
to transform array element into something else.
result = [1,2,3].map { |number| "num-#{number}" }
# result: ["num-1", "num-2", "num-3"]
collect
just alias to map
and has same functionality.
result = [1,2,3].collect { |number| number.to_s }
# result: ["1", "2", "3"]
select
to select array element which the expression return true
result = [1,2,3,4].select { |number| number.odd? }
# result: [1, 3]
filter
just alias to select
and has same functionality.
result = [1,2,3,4].filter { |number| number > 3 }
# result: [4]
reject
is opposite of select, filter
, to select array element which the expression return false
result = [1,2,3,4].reject { |number| number.odd? }
# result: [2, 4]
flat_map
to map nested array into 1 dimensional.
result = [[1,1,1],[2,2,2]].flat_map{ |n| n }
# result: [1, 1, 1, 2, 2, 2]
result = ['x','y'].flat_map do |letter|
[1,2,3].map do |number|
"#{letter}#{number}"
end
end
# result: ["x1", "x2", "x3", "y1", "y2", "y3"]
flatten
to return new array as 1 dimensional flattening of this array (recursively).
result = [['a'],['b'],['c']].flatten
# result: ["a", "b", "c"]
result = [[['a']],[['b']],[['c']]].flatten(1)
# result: [["a"], ["b"], ["c"]]
partition
to return 2 set of array which the first element is from expression that returns true
and next element is from expression that returns false
.
result = [1,2,3,4].partition { |number| number.odd? }
# result: [[1, 3], [2, 4]]
# destructuring with partition
select,reject = [1,2,3,4].partition { |number| number.odd? }
# select: [1,3]
# reject: [2,4]
count
to count elements for which expression returns true
.
result = [1,1,2,3,3,4,4].count { |number| number.odd? }
# result: 4
find
to return the first element for which expression returns true
.
result = [1,2,3,4].find { |number| number.even? }
# result: 2
detect
just alias to find
and has same functionality.
result = [1,2,3,4].detect { |number| number % 2 == 0 }
# result: 2
reduce
to takes an accumulator and changes it as the elements in array, return the final value of the accumulator.
result = ['a','b','c','d'].reduce { |join,letter| join += letter }
# result: "abcd"
inject
just alias to reduce
and has same functionality.
result = [1,2,3,4].reduce { |sum,number| sum += number }
# result: 10
.with_index
can be applied for each, map, select
['a','b','c'].each.with_index { |char,index| puts "#{index}:#{char}" }
# result:
0:a
1:b
2:c
result = ['a','b','c'].map.with_index { |char,index| "#{index}:#{char}" }
# result: ["0:a", "1:b", "2:c"]
result = ['a','b','c','d'].select.with_index { |char,index| index.odd? }
# result: ["b", "d"]
Array methods which are return array also can be chained.
arr = [1,2,3,4,5]
result = arr
.map{ |n| n ** 2}
.select{ |n| n.even? }
.reject{ |n| n > 10}
.count{ |n| n.odd? }
# result: 0
group_by
to group array element by some arbitrary property, and return as hash.
fruits = ['apple','banana','avocado','coconut','citrus','blueberries']
result = fruits.group_by { |fruit| fruit[0] }
# result:
# {
# "a"=>["apple", "avocado"],
# "b"=>["banana", "blueberries"],
# "c"=>["coconut", "citrus"]
# }
arr = ['abc',1,2,'xyz',true,false,3.5,true,4.24]
result = arr.group_by { |e| e.class }
# result:
# {
# String=>["abc", "xyz"],
# Integer=>[1, 2],
# TrueClass=>[true, true],
# FalseClass=>[false],
# Float=>[3.5, 4.24]
# }
For array element class methods, we can call it by Ruby syntactic sugar, it will make code more readable & concise.
result = [1,2,3,4].map &:to_s
# result: ["1", "2", "3", "4"]
result = [1,2,3,4].select &:odd?
# result: [1,3]
Since: Ruby 2.7.0
We can omit arguments inside block with numbered argument or argument alias.
# instead of..
result = [1,2,3].map { |number| number.to_s }
# we can use
result = [1,2,3].map { _1.to_s }
# result: ["1", "2", "3"]
['a','b','c'].each.with_index { puts "#{_2}:#{_1}" }
# result:
0:a
1:b
2:c